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

在前两篇的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可以阻止继承和多态

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值