JDK 动态了解了,来了解下cglib的动态代理。
cglib动态代理底层是通过使用一个小而快的字节码处理框架ASM(Java字节码操控框架),来转换字节码并生成新的类。
简单但不完全准确的说,就是给定父类,生成该父类的子类,然后在生成的子类里重写父类的方法,并加入子类的逻辑,但保留父类的逻辑(可以看看源码,但是现在还不想看,里面又是f1,f2,i1,i2的看的头晕,先记录下使用步骤吧)。
主要角色有:被代理对象+代理对象(一个实现了MethodInterceptor接口的类)+代理工厂+调用方
前提:引入对应的包
asm.jar
cglib.jar
asm-commons.jar
asm-tree.jar
注意下版本问题
1.创建被代理对象
package com.wdr.practice.cglibproxy; public class Target { public void doTargetMethod(){ System.out.println("doTargetMethod"); } }
2.创建代理对象
package com.wdr.practice.cglibproxy; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class TargetProxy implements MethodInterceptor { // 重写intercept ,在该方法中对被代理对象的方法前后加逻辑 @Override public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { beforeMethod(); Object returnVal = methodProxy.invokeSuper(target, args); aftreMethod(); return returnVal; } private void beforeMethod(){ System.out.println("beforeMethod"); } private void aftreMethod(){ System.out.println("aftreMethod"); } }
3.代理工厂
package com.wdr.practice.cglibproxy; import net.sf.cglib.proxy.Enhancer; public class ProxyFactory { //维护一个目标对象 ,即被代理的对象 private Object targetObj; // getter &setter 或者带target的构造函数都行 public Object getTargetObj() { return targetObj; } public void setTargetObj(Object targetObj) { this.targetObj = targetObj; } // //构造器,传入一个被代理的对象 // public ProxyFactory(Object target) { // this.targetObj = target; // } // 生成代理对象 public static Object getProxyInstance(Class<?> clazz){ // 工具类 Enhancer enhancer = new Enhancer(); // 设置代理类的父类:如果是接口的话,是赋值接口类数组;如果不是接口的话,赋值父类 enhancer.setSuperclass(clazz); // 设置回调函数 enhancer.setCallback(new TargetProxy()); // 返回创建的代理对象 return enhancer.create(); } }
4.调用
package com.wdr.practice.cglibproxy; public class Client { public static void main(String[] args) { Target target = new Target(); ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setTargetObj(target); Target targetProxy = (Target)proxyFactory.getProxyInstance(target.getClass()); targetProxy.doTargetMethod(); } }
输出结果:
留几个问题:
1、代理工厂的getProxyInstance方法里Enhancer工具类的用法
2、methodProxy.invokeSuper(target, args)这个方法的具体逻辑
3、TargetProxy#intercept 这个方法什么时候调用的
4、被代理对象里的方法有什么要求,什么情况会被代理,什么情况会不被代理