学习CGLIB与JDK动态代理的区别
程序员文章站
2022-04-06 13:11:54
动态代理 代理模式是Java中常见的一种模式。代理又分为静态代理和动态代理。静态代理就是显式指定的代理,静态代理的优点是由程序员自行指定代理类并进行编译和运行,缺点是一个代理类只能对一个接口的实现类进行包装,多个代理类存在重复代码,因此可以定义这样一个代理类,它能代理所有实现类的方法调用:根据传进来 ......
-
动态代理
- 代理模式是Java中常见的一种模式。代理又分为静态代理和动态代理。静态代理就是显式指定的代理,静态代理的优点是由程序员自行指定代理类并进行编译和运行,缺点是一个代理类只能对一个接口的实现类进行包装,多个代理类存在重复代码,因此可以定义这样一个代理类,它能代理所有实现类的方法调用:根据传进来的实现类和方法名进行具体调用。——这就是动态代理。
-
JDK动态代理
- 先上代码,一个接口类
-
1 package com.example.demo; 2 3 public interface IWrite { 4 //写 5 void write(); 6 }
- 一个实现类
1 package com.example.demo; 2 3 public class Author implements IWrite { 4 @Override 5 public void write() { 6 System.out.println("writing"); 7 } 8 }
- 最后是代理类
package com.example.demo; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class AuthorProxy implements InvocationHandler { private Object target; public Object bind(Object target) { this.target = target; //接收业务实现类对象参数 //通过反射机制,创建一个代理类对象实例并返回。用户进行方法调用时使用 //创建代理对象时,需要传递该业务类的类加载器(用来获取业务实现类的元数据,在包装方法是调用真正的业务方法)、接口、handler实现类 return Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(),this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before"); method.invoke(target,args); System.out.println("after"); return null; } public static void main(String args[]) { Author write = new Author(); AuthorProxy authorProxy = new AuthorProxy(); IWrite author = (IWrite) authorProxy.bind(write); author.write(); } }
- jdk动态代理:代理所有“实现的有接口”的目标类。使用内置的Proxy实现动态代理有一个问题:被代理的类必须实现接口,未实现接口则没办法完成动态代理。
-
CGLib动态代理
- 还是先上代码,一个不继承接口的业务类
package com.example.demo; public class AuthorNoImplements { public void write() { System.out.println("writing..."); } }
- 最后是代理实现与测试
package com.example.demo; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class CglibProxy implements MethodInterceptor { private Object target; // 这里的目标类型为Object,则可以接受任意一种参数作为被代理类,实现了动态代理 public Object bind(Object target) { this.target = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass()); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("before"); Object obj = method.invoke(target, objects); System.out.println("after"); return obj; } public static void main(String args[]) { CglibProxy cglibProxy = new CglibProxy(); AuthorNoImplements authorNoImplements = (AuthorNoImplements) cglibProxy.bind(new AuthorNoImplements()); authorNoImplements.write(); } }
-
CGlib动态代理是通过继承业务类,生成的动态代理类是业务类的子类,通过重写业务方法进行代理;
-
CGLib 与JDK动态代理的区别
- 最后说一下二者的区别:
- JDK代理是不需要以来第三方的库,只要要JDK环境就可以进行代理,它有几个要求
* 实现InvocationHandler
* 使用Proxy.newProxyInstance产生代理对象
* 被代理的对象必须要实现接口 - CGLib 必须依赖于CGLib的类库,但是它需要类来实现任何接口代理的是指定的类生成一个子类,覆盖其中的方法,是一种继承但是针对接口编程的环境下推荐使用JDK的代理。
上一篇: 剑指Offer_编程题之重建二叉树