cglib实现动态代理简单使用
Boss:
package proxy.cglib; public class Boss{ public void findPerson() { System.out.println("我要找java架构师"); } }
WebApp:
import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * 方法拦截器 * CGLib 代理的目标对象不需要实现任何接口,它是通过动态继承目标对象 实现的动态代理 */ public class WebApp implements MethodInterceptor { public Object getInstance(Class<?> clazz){ Enhancer enhancer = new Enhancer(); //告诉cglib,生成的子类需要继承哪个类 enhancer.setSuperclass(clazz); //设置回调 enhancer.setCallback(this); //生成源代码 //编译成class文件 //加载到JVM中,并返回被代理对象 return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { //这个obj的引用是由CGLib给我们new出来的 //cglib new出来以后的对象,是被代理对象的子类 //在new子类之前,实际上默认先调用了我们super()方法的, //new子类的同时,必须先new出来父类,这就相当于是间接的持有了我们父类的引用 //子类重写了父类的所有的方法 //我们改变子类对象的某些属性,是可以间接的操作父类的属性的 before(); Object obj = methodProxy.invokeSuper(o, objects);//这里是调父类的(子类死循环) after(); return obj; } private void after() { System.out.println("---------------"); } private void before() { System.out.println("找Person,找我WebApp cglib"); System.out.println("---------------"); } }
Test:
package proxy.cglib; /** * JDK的动态代理是通过接口来进行强制转换的 * 生成以后的代理对象,可以强制转换为接口 * *CGLib的动态代理是通过生成一个被代理对象的子类,然后重写父类的方法 * 生成以后的对象,可以强制转换为被代理对象 * 子类引用赋值给父类 */ public class Test { public static void main(String[] args){ try { Boss boss = (Boss) new WebApp().getInstance(Boss.class); boss.findPerson(); }catch (Exception e){ e.printStackTrace(); } } }
将 CGLib 代理 后的 class 写入到磁盘,然后,我们再反编译一探究竟
CGLib 和 JDK 动态代理对比
1.JDK 动态代理是实现了被代理对象的接口,CGLib 是继承了被代理对象。
2.JDK 和 CGLib 都是在运行期生成字节码,JDK 是直接写 Class 字节码,CGLib 使用 ASM
框架写 Class 字节码,Cglib 代理实现更复杂,生成代理类比 JDK 效率低。
3.JDK 调用代理方法,是通过反射机制调用,CGLib 是通过 FastClass 机制直接调用方法,
CGLib 执行效率更高