【设计模式】Java设计模式 - 动态代理
【设计模式】Java设计模式 - 动态代理
不断学习才是王道
继续踏上学习之路,学之分享笔记
总有一天我也能像各位大佬一样
一个有梦有戏的人 @怒放吧德德
最近工作比较忙,没啥时间学习
1、简介
动态代理是指客户通过代理类来调用其它对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象。动态代理就需要建立真实对象和代理对象关系,再去实现代理逻辑方法。
Java中实现动态代理有许多方法,JDK、CGLIB、Javassist、ASM,常用的是JDK和CGLIB,在spring中就是使用了这两种,然而mybatis还是用了Javassist。
2、JDK动态代理
提供简单的接口类以及其实现类,在通过建立真是对象与代理对象的关系,并且实现代理逻辑。
(1)、准备接口类
先提供接口类:
HelloWorldService:
package com.lyd.demo.service;
/**
* @Author: lyd
* @Description: 普通的接口
* @Date: 2022-08-17
*/
public interface HelloWorldService {
public void sayHelloWorld();
}
HelloWorldServiceImpl:
package com.lyd.demo.service.impl;
import com.lyd.demo.service.HelloWorldService;
/**
* @Author: lyd
* @Description: 接口实现类
* @Date: 2022-08-17
*/
public class HelloWorldServiceImpl implements HelloWorldService {
@Override
public void sayHelloWorld() {
System.out.println("Hello World!");
}
}
(2)、jdk动态代理
在JDK动态代理中,通过bind将真实对象和代理对象绑定起来,实现代理逻辑就要去实现java.lang.reflect.InvocationHandler接口,并且去实现invoke方法
①、首先需要声明 bind 方法去建立真实对象与代理对象的关系,把本类中的target保存真实对象。在通过Proxy的newProxyInstance方法来建立并生成对象,target.getClass().getClassLoader():target本身的类加载器,target.getClass().getInterfaces():把生成的动态代理对象下挂在接口中,this:当前对象,是定义实现方法逻辑的代理类。
②、实现InvocationHandler类中的invoke方法,可以实现代理逻辑,当我们使用了代理对象调度方法后就会进入到invoke方法中。
代码如下:
package com.lyd.demo.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Author: lyd
* @Description: 动态代理绑定和代理逻辑实现
* @Date: 2022-08-17
*/
public class JdkProxyExample implements InvocationHandler {
// 真实对象
private Object target = null;
/**
* 建立代理对象和真实对象的代理关系,并且返回代理逻辑实现
* @param target 真实对象
* @return 代理对象
*/
public Object bind(Object target) {
this.target = target; // 绑定对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
/**
* 代理方法逻辑
* @param proxy 代理对象
* @param method 当前调度方法
* @param args 当前方法的参数
* @return 代理结果返回
* @throws Throwable 异常
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("进入代理逻辑方法");
System.out.println("在调度真实对象之前的服务");
Object obj = method.invoke(target, args); // 相当于调用了sayHelloWorld的方法
System.out.println("在调度真实对象之后的服务");
return obj;
}
}
(3)、实例
测试jdk动态代理
通过 HelloWorldService proxy = (HelloWorldService) jdkProxyExample.bind(new HelloWorldServiceImpl()); 去代理对象,然后就是使用proxy去点接口里面的方法了。
代码如下:
package com.lyd.demo.test;
import com.lyd.demo.jdk.JdkProxyExample;
import com.lyd.demo.service.HelloWorldService;
import com.lyd.demo.service.impl.HelloWorldServiceImpl;
/**
* @Author: lyd
* @Description: 测试jdk动态代理
* @Date: 2022-08-17
*/
public class jdkProxyText {
public static void main(String[] args) {
JdkProxyExample jdkProxyExample = new JdkProxyExample();
// 绑定关系,因为挂载带接口下,因此声明一个代理对象
HelloWorldService proxy = (HelloWorldService) jdkProxyExample.bind(new HelloWorldServiceImpl()); // 对象是new 实现类
// 调用方法
proxy.sayHelloWorld();
}
}
实验结果

可以带入参数:以下是带入参数的例子
在接口中的方法添加参数
public void sayHelloWorld(String name);
在实现类的实现方法中打印出来
System.out.println("Hello World! " + name);
调用方法的时候添加参数
// 调用方法
proxy.sayHelloWorld("lyd");
代理模式十分重要,要理解里面的逻辑,可以通过debug打断点去一步一步查看。
3、CGLIB 动态代理
JDK动态代理需要接口才能完成,而如果不提供接口,只有实现的方法类,可以使用三方插件CGLIB来动态代理,采用这个动态代理技术,需要引入三方jar包,可以搭建maven项目,引入CGLIB jar包 ,通过maven官网搜索添加,亦可以直接下载jar文件。
(1)、加入CGLIB依赖
maven引入依赖:
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
(2)、准备实现类
准备一个实现类,cglib不需要接口,只要实现就可以:
package com.lyd.demo.impl;
/**
* @Author: lyd
* @Description: 实现类
* @Date: 2022-08-17
*/
public class HelloWorldServiceImpl {
public void sayHelloWorld(String name) {
System.out.println("Hello World! " + name);
}
}
(3)、代理类
代理类需要MethodInterceptor去实现方法
这里使用了增强者enhancer,通过设置超类和使用setCallback方法设置代理类,CGLIB是通过invokeSuper方法代理逻辑的。
package com.lyd.demo.cglib;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @Author: lyd
* @Description:
* @Date: 2022-08-17
*/
public class CglibProxyExample implements MethodInterceptor {
/**
* 生成CGLIB对象
* @param cls -----对象类
* @return Class的CGLIB代理对象
*/
public Object getProxy(Class cls) {
//CGLIB的增强类对象
Enhancer enhancer = new Enhancer();
//设置增强对象
enhancer.setSuperclass(cls);
//定义代理逻辑对象为当前对象,要求对象实现MethodInterceptor方法
enhancer.setCallback(this);
//生成返回代理对象
return enhancer.create();
}
/**
* 代理逻辑方法
* @param proxy 代理对象
* @param method 方法
* @param args 参数
* @param methodProxy 方法代理
* @return 代理逻辑返回
* @throws Throwable 异常处理
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("调用对象之前");
//使用CGLIB反射真实对象的方法
Object result = methodProxy.invokeSuper(proxy, args);
System.out.println("调用对象之后");
return result;
}
}
(4)、实例
测试:
package com.lyd.demo.test;
import com.lyd.demo.cglib.CglibProxyExample;
import com.lyd.demo.impl.HelloWorldServiceImpl;
/**
* @Author: lyd
* @Description: 测试CGLIB
* @Date: 2022-08-17
*/
public class CGLIBProxyTest {
public static void main(String[] args) {
CglibProxyExample cglibProxyExample = new CglibProxyExample();
HelloWorldServiceImpl proxy = (HelloWorldServiceImpl) cglibProxyExample.getProxy(HelloWorldServiceImpl.class); // 获取对象,可以不需要接口类
proxy.sayHelloWorld("lyd");
}
}
结果

【设计模式】Java设计模式 - 动态代理的更多相关文章
- java设计模式中的动态代理
Java的三种代理模式 1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩 ...
- 设计模式之jdk动态代理模式、责任链模式-java实现
设计模式之JDK动态代理模式.责任链模式 需求场景 当我们的代码中的类随着业务量的增大而不断增大仿佛没有尽头时,我们可以考虑使用动态代理设计模式,代理类的代码量被固定下来,不会随着业务量的增大而增大. ...
- java中动态代理实现机制
前言: 代理模式是常用的java设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系 ...
- [转载] java的动态代理机制详解
转载自http://www.cnblogs.com/xiaoluo501395377/p/3383130.html 代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代 ...
- java的动态代理机制详解
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...
- Java特性-动态代理
代理在开发中无处不在: 我们完成一个接口开发A,接口下有很多个实现类,这些类有些共同要处理的部分,比如每一个类都定义了接口A中的方法getXX(String name).我现在想把每次调用某个实现类的 ...
- java的动态代理机制
前几天看到java的动态代理机制,不知道是啥玩意,然后看了看.死活不知道 invoke(Object proxy, Method m, Object[] args)种的proxy是个什么东西,放在这里 ...
- java中动态代理
一.在java中怎样实现动态代理 1.我们要有一个接口,还要有一个接口的实现类,而这个实现类呢就是我们要代理的对象 接口: package org.dynamicproxy.test; public ...
- Java的动态代理机制详解(转)
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...
- (转)java的动态代理机制详解
原文出自:http://www.cnblogs.com/xiaoluo501395377/p/3383130.html 在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一 ...
随机推荐
- Python实现12种概率分布(附代码)
今天给大家带来的这篇文章是关于机器学习的,机器学习有其独特的数学基础,我们用微积分来处理变化无限小的函数,并计算它们的变化:我们使用线性代数来处理计算过程:我们还用概率论与统计学建模不确定性. 在这其 ...
- c# 反射专题—————— 介绍一下是什么是反射[ 一]
前言 为什么有反射这个系列,这个系列后,asp net 将会进入深入篇,如果没有这个反射系列,那么asp net的源码,看了可能会觉得头晕,里面的依赖注入包括框架源码是大量的反射. 正文 下面是官方文 ...
- 【docker专栏4】使用docker安装nginx提供web服务
一般学习一项技术,会先用一个最简单的例子或最典型的例子来向大家讲解入门内容,所以此文为大家介绍使用docker安装nginx容器服务.从基础使用的角度来讲,此文几乎涵盖了docker最核心的内容:镜像 ...
- 如何优化API?8个实用技巧!【eolink翻译】
使用 API 可以让公司利用现代连接的力量来帮助他们扩大全球影响力.传输数据和改进集成.由于 API 使企业能够简化流程并增强可用性,所以企业会使用一些优化策略,不断优化流程,比如接下来要说到的8个技 ...
- Solution -「原创」Destiny
题目背景 题目背景与题目描述无关.签到愉快. 「冷」 他半靠在床沿,一缕感伤在透亮的眼眸间荡漾. 冷见惆怅而四散逃去.经历嘈杂喧嚣,感官早已麻木.冷又见空洞而乘隙而入.从里向外,这不是感官的范畴. 他 ...
- 自定义注解_格式&本质和自定义注解_属性定义
自定义注解: 格式: public @interface 注解名称{} 本质:注解本质上就是一个接口,该接口默认继承Annotation接口 public interface MyAnno exten ...
- CF Round #808 题解 (Div. 2 ABCD)
后面题太难搞不动 . ABCD 的题解写的好水啊,感觉在写闲话,,, A 若 \(\forall i, a_1\mid a_i\),则可以 . 注意判 \(0\) 的情况 . 提交记录 . B 显而易 ...
- 丽泽普及2022交流赛day16 社论
这场比较平凡吧 . 省流: http://zhengruioi.com/contest/1087 目录 目录 A. Gene 题面 题解 算法一(正解) 算法二 B. Fight 题面 题解 算法一( ...
- 面试突击69:TCP 可靠吗?为什么?
相比于 UDP 来说,TCP 的主要特性是三个:有连接.可靠.面向数据流.所谓的"有连接"指的是 TCP 中的连接管理机制,也就是著名的三次握手和四次挥手,就像打电话一样,想要正常 ...
- SElinux管理
SElinux: 是Linux的一个强制访问控制的安全模块 SElinux的相关概念: 对象:文件.目录.进程.端口等 主体:进程称为主体 SElinux将所有的文件都赋予一个type类型的标签,所有 ...