天天看点

WHWW之代理模式(3)-cglib动态代理

What:什么是cglib动态代理?

cglib动态代理是由第三方类库实现的代理,使用要添加cglib jar包,其代理底层是借助 asm来实现的。( asm是java虚拟机里面的一种动态生成字节码的技术,跟反射是不同的)

How:怎么实现cglib动态代理呢?

/**
 * 目标对象类
 */
public class Target {
    public void sayHello() {
        System.out.println("你好");
    }
}
      
/**
 * cglib动态代理
 */

public class CGLibDynamicProxy implements MethodInterceptor {

    //目标对象
    private  Object target;

    /**
     * 创建代理对象
     * @param target
     * @return
     */
    public Object getInstance(Object target){
        this.target=target;

        //用这个类 来创建代理对象(被代理类的子类);并设置父类;设置回调。
        //Enhancer该类是cglib jar包中的类
        Enhancer enhancer=new Enhancer();

        //设置被代理类作为其父类的代理目标
        enhancer.setSuperclass(this.target.getClass());

        //设置回调方法,当这个代理对象方法被调用时,回调方法intercept()会被执行
        enhancer.setCallback(this);

        //返回创建的代理对象
        return enhancer.create();
    }

    /**
     * 回调方法
     * @param o
     * @param method
     * @param objects
     * @param methodProxy 代理的类的方法(会调用父类被代理的方法)
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        Object result=null;
        before();//前置增强
        result=methodProxy.invokeSuper(o,objects);
        after();//后置增强

        return result;
    }

    /**
     * 在实现方法前可以做的事情
     */
    public  void  before(){
        System.out.println("摘下耳机");
    }

    /**
     * 在实现方法后做的事情
     */
    public void after(){
        System.out.println("戴上耳机");
    }

}
      
/**
 * cglib动态代理测试端
 */
public class CglibProxyTest {

    public static void main(String[] args) {
        CGLibDynamicProxy cgLibDynamicProxy=new CGLibDynamicProxy();
        //生成代理对象
        Target hello=(Target) cgLibDynamicProxy.getInstance(new Target());
        //当调用代理对象的被代理方法时,会自动回调,调用CGLibDynamicProxy代理类中的Intercept()方法
        hello.sayHello();

    }
}
      

控制台输出:

摘下耳机

你好

戴上耳机

Process finished with exit code 0

Why:为什么要用cglib动态代理?

因为jdk动态代理只能代理实现了接口的类,如果该目标类没有实现任何接口,则不能使用jdk动态代理,可以看下WHWW之代理模式(2)-动态代理。而cglib动态代理是针对类来实现的,也就是说这个目标类可以不用实现任何接口,cglib动态代理都可以对该类进行代理。

注:因为cglib动态代理采用的是继承,所以不能对final修饰的类进行代理

Where:哪些地方使用cglib动态代理?

spring Aop的底层实现就用到cglib动态代理,如果我们要对没有实现接口的类进行功能扩展时,也可以考虑cglib动态代理。

继续阅读