Java动态代理
Created|Updated
|Word Count:910|Post Views:
动态代理实现:
1、JDK 动态代理
用 Java 反射包中的类和接口实现动态代理
2、CGLIB 动态代理
通过第三方库 CGLIB ,以继承类的方式实现动态代理
JDK 代理
由于底层机制的缘故,被代理的目标类必须实现至少一个接口
- 创建被代理的目标类以及其实现的接口
- 创建
InvocationHandler
接口的实现类,在 invoke()
中完成要代理的功能
- 用
Proxy.newInstance()
动态地构造出代理对象
Hello (被代理的目标类实现的接口)
1 2 3 4 5
| public interface Hello { void sayHello();
int plus(int a, int b); }
|
HelloImpl (被代理的目标类)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class HelloImpl implements Hello {
@Override public void sayHello() { System.out.println("sayHello方法被调用"); }
@Override public int plus(int a, int b) { int c = a + b; System.out.println("plus方法被调用"); System.out.println("返回值为" + c); return c; } }
|
MyProxyHandler (InvocationHandler的实现类)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| public class MyProxyHandler implements InvocationHandler {
private Object target = null;
public MyProxyHandler(Object target) { this.target = target; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
System.out.println(method);
Object res = null; res = method.invoke(target, args);
after();
return res; }
public void before() { System.out.println("before"); }
public void after() { System.out.println("after"); } }
|
Main (主方法)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public class Main { public static void main(String[] args) { HelloImpl helloImpl = new HelloImpl(); MyProxyHandler myProxyHandler = new MyProxyHandler(helloImpl); Hello helloProxy = (Hello) Proxy.newProxyInstance(helloImpl.getClass().getClassLoader(), helloImpl.getClass().getInterfaces(), myProxyHandler); helloProxy.sayHello(); System.out.println("=========="); helloProxy.plus(1, 1); } }
|
JDK 代理生成的代理对象实际上是在原对象的基础上,给每个方法都用 invoke()
进行了加强
相较于静态代理,使用少量的代码就可以完成增强效果
CGLIB 代理
需要导入jar包:核心包和依赖包(spring_core.jar已经集成了这两个包,因此,导入此包即可)
子类是在调用的时候才生成的
使用目标对象的子类的方式实现的代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展,能够在运行时动态生成字节码,可以解决目标对象没有实现接口的问题
缺点:被final或static修饰的类不能用cglib代理,因为它们不会被拦截,不会执行目标对象的额外业务方法
[Java 动态代理详解 - whirlys - 博客园 (cnblogs.com)](https://www.cnblogs.com/whirly/p/10154887.html#:~:text=Java 动态代理详解. 动态代理在Java中有着广泛的应用,比如Spring,AOP、Hibernate数据查询、测试框架的后端mock、RPC远程调用、Java注解对象获取、日志、用户鉴权、全局性异常处理、性能监控,甚至事务处理等。. 本文主要介绍Java中两种常见的动态代理方式:JDK原生动态代理和CGLIB动态代理。. 由于Java动态代理与java反射机制关系紧密,请读者确保已经了解了Java反射机制 )