设计模式——代理模式:CGLIB动态代理

前言

关于jdk实现代理模式的AOP代理和详解主要放在本文中:设计模式——代理模式:JDK静态代理和动态代理的实例和实现。本文相对于jdk的代理模式,内容较为少,主要体现cglib代理模式实现动态代理AOP和cglib实现动态代理AOP的区别以及实例Demo。

CGLIB和JDK实现AOP的区别

JDK动态代理只能为接口实现动态代理。而不能对没有通过接口定义业务方法的类动态代理(因为jdk代理实现的实例对象会继承Proxy类,java的单继承原则使得他不能代理实现继承类对象);

JDK的动态代理通过ProxyGenerator.generateProxyClass()生成代理类的字节码,由Proxy.defineClass0()加载,可以看到这个代理类 extends Proxy implements Interface1, … {…}。

所以在jdk代理实现一文中实现的代理类对象都是实现接口:

public class Boy implements Human,YoungMan{

Cglib:利用ASM框架,对代理对象类生成的class文件加载进来,通过修改其字节码生成子类来处理。是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,并覆盖其中方法的增强,但是因为采用的是继承,所以该类或方法最好不要生成final。对于final类或方法,是无法继承的。

什么时候使用jdk动态代理?什么时候使用cglib动态代理?

以Spring的Bean对象来举例:

  1. 目标对象实现了接口,默认用JDK动态代理;
  2. 目标对象实现了接口,可强制使用CGLIB动态代理;(在spring配置中加入<aop:aspectj-autoproxy proxyt-target-class=”true”/>)
  3. 目标对象没有实现接口,必须采用CGLIB动态代理;

示例代码

实体类

public class Man {
    public void sayHello(){
        System.out.println("Hello Cglib");
    }
}

cglib代理类

public class CglibProxy implements MethodInterceptor {

    private Enhancer enhancer = new Enhancer();

    public Object getProxy(Class clazz){
        //设置需要创建子类的类
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        //通过字节码技术动态创建子类实例
        //拿到一个cglib动态生成的代理类(这个类继承自被代理类)
        return enhancer.create();
    }
    
    /**自定义的前缀方法**/
    private void pre() {
    	System.out.println("pre");
    }
    
    private void after() {
		System.out.println("after");
	}

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    	this.pre();
        System.out.println("前置代理");
        //通过代理类调用父类中的方法
        Object result = methodProxy.invokeSuper(o, objects);
        System.out.println("后置代理");
        this.after();
        return result;
    }
}

测试类

public class CglibMain {
    public static void main(String[] args) {
        CglibProxy proxy = new CglibProxy();
        //通过生成子类的方式创建代理类
        Man proxyImp = (Man) proxy.getProxy(Man.class);
        proxyImp.sayHello();
    }
}

上一篇:Cglib Callback使用、如何进行反编译


下一篇:cglib源码分析(四):cglib 动态代理原理分析