一、什么是动态代理?
动态代理是一种编程模式,它允许在运行时创建代理对象,以实现对目标对象的方法进行增强,代理对象同名方法内可以执行原有逻辑的同时嵌入执行其他增强逻辑或者其他对象方法。
二、动态代理的作用
需要将一些非主的公共逻辑无侵入性的应用到某个业务代码逻辑上,例如:日志记录、事务管理、性能监控等,既降低代码的耦合度,也减少代码的重复性。
三、动态代理的使用场景
1、Spring AOP
2、自己手动创建代理对象
四、动态代理的实现技术
1、JDK动态代理技术(基于接口):
(1)使用条件:要求被代理类有接口,代理对象是基于接口动态生成的实现类。
(2)使用方式:
A、在Spring AOP中,目标类有接口的情况下,默认采用该代理技术。
B、在自己需要手动创建代理对象的时候:
// 声明一个接口
public interface JDKService {
void show(String s);
}
// 进行接口实现
public class JDKServiceImpl implements JDKService{
@Override
public void show(String s) {
System.out.println("JDKService show......"+s);
}
}
// 主测试代码
public class JDKProxyDemo {
public static void main(String[] args) {
JDKService jdkService = new JDKServiceImpl();
// 使用 JDK动态代理技术,创建代理对象
Object proxyInstance = Proxy.newProxyInstance(
jdkService.getClass().getClassLoader(),
jdkService.getClass().getInterfaces(),
(Object proxy, Method method, Object[] arg) -> {
// proxy:代理对象,method:执行的目标对象方法,arg:执行的目标对象方法参数列表
System.out.println("proxy:" + proxy.getClass());
Object result = method.invoke(jdkService, arg);
System.out.println("arg:" + arg);
return result;
});
JDKService proxy= (JDKService) proxyInstance;
proxy.show("hello");
}
}
/**
* 执行结果:
* 方法调用前执行一些逻辑.......
* JDKService show......hello
* 方法调用后执行一些逻辑.......
*/
2、Cglib动态代理技术(基于子类):
(1)使用条件:被代理类无接口且不能使用final修饰,代理对象是基于被代理对象动态生成的子对象。
(2)使用方式:
A、在 Spring AOP中,手动配置 <aop:config proxy-target-class="true">强制使用 Cglib方式。
B、在自己需要手动创建代理对象的时候:
// 被代理对象,也就是目标类
public class Target {
public void show(String s){
System.out.println("Target show.........."+s);
}
}
// 增强逻辑
public class Advice {
public void before(){
System.out.println("Advice before ......");
}
public void after(){
System.out.println("Advice after .......");
}
}
// 主测试类
public class CglibProxyDemo {
public static void main(String[] args) {
Target target = new Target();// 目标对象
Advice advice = new Advice();// 增强对象
Enhancer enhancer = new Enhancer(); // 用来实现 Cglib动态代理的增强器对象
enhancer.setSuperclass(target.getClass());// 注意用的都是 spring下的spring-core中的类
// 设置增强器回调
enhancer.setCallback((MethodInterceptor)(o, method, objects, methodProxy)->{
advice.before();
Object result = method.invoke(target,objects);
advice.after();
return result;
});
// 创建代理对象
Target proxy = (Target) enhancer.create();
proxy.show("hello");
}
}
/**
* 执行结果:
* Advice before ......
* Target show..........hello
* Advice after .......
*/