设计模式--CGLib动态代理的实现与解析

来源:互联网 发布:百度php面试题 编辑:程序博客网 时间:2024/06/11 20:08

在前两篇的JDK动态代理中,它是通过Proxy类和实现InvocationHandler接口实现的。但是此方式最大的缺点是:要求被代理的目标类必须实现一个接口,而且只能对接口中的方法实现代理。因为最终生成的代理类是继承了Proxy类以及实现了目标类的接口。
如果被代理的目标类没有实现接口,JDK就无法完成代理。这时,可以采用CGLib动态代理。JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。
Cglib是一个强大的,高性能,高质量的代码生成类库。它可以在运行期扩展JAVA类与实现JAVA接口。其底层实现是通过ASM字节码处理框架来转换字节码并生成新的类。大部分功能实际上是ASM所提供的,Cglib只是封装了ASM,简化了ASM操作,实现了运行期生成新的class。CGLib在运行时动态的生成一个被代理类的子类(通过ASM字节码处理框架实现),子类重写了被代理类中所有非final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势植入横切逻辑。
拦截器:实现MethodInterceptor接口的类,在intercept方法中实现对代理目标类的方法拦截。
Enhancer类,来生成代理类。

CGLib动态代理实现:

先看如何实现:
目标类(被委托类)

package com.blog.cglibproxy;/** * @Description: * @Author: Jingzeng Wang * @Date: Created in 16:01  2017/6/27. */public class UserDao {    /**     * 目标类的add方法     */    public void add() {        System.out.println("目标类的添加方法!!");    }    /**     * 目标类的delete方法     */    public void delete() {        System.out.println("目标类的删除方法!!");    }}

代理逻辑,实现了MethodInterceptor 的intercept()方法:

package com.blog.cglibproxy;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/** * @Description: 代理逻辑 * @Author: Jingzeng Wang * @Date: Created in 17:12  2017/6/27. */public class MyInterceptor implements MethodInterceptor {    private Enhancer enhancer = new Enhancer();    public Object getProxy(Class clazz) {        //设置目标类        enhancer.setSuperclass(clazz);        //设置拦截实现类        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 result = methodProxy.invokeSuper(o, objects);        System.out.println("-------------------after------------------");        return result;    }}

测试类:

package com.blog.cglibproxy;/** * @Description: * @Author: Jingzeng Wang * @Date: Created in 17:19  2017/6/27. */public class Test {    public static void main(String[] args) {        MyInterceptor myInterceptor = new MyInterceptor();        UserDao proxy = (UserDao) myInterceptor.getProxy(UserDao.class);        proxy.add();        proxy.delete();    }}

其结果为:

-------------------before-----------------目标类的添加方法!!-------------------after-------------------------------------before-----------------目标类的删除方法!!-------------------after------------------

这就实现了对目标类的代理。生成的代理类是直接操作字节码继承了目标类。

CGLib动态代理与JDK动态代理的区别
CGLib主要是对指定的类生成一个子类,覆盖其中的所有方法,所以该类或方法不能声明称final的。JDK动态代理只能对实现了接口的类生成代理,而不能针对类 。CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法 。因为是继承,所以该类或方法最好不要声明成final ,final可以阻止继承和多态

阅读全文
0 0
原创粉丝点击