CGLib动态代理

在spring AOP中,通常会用cglib动态代理来生成AOProxy对象。cglib动态代理和JDk动态代理的不同之处在于cglib动态代理是通过继承被代理类,生成的动态代理类是被代理类的子类,然后通过重写业务方法来实现代理。

1、定义被代理类

public class cglibPerson {

    public void findLove(){
        System.out.println("肤白貌美大长腿");
    }
}

2、定义代理类媒婆

public class cglibMeipo implements MethodInterceptor {

    //好像并没有持有被代理对象的引用,也就是好像不满足都动态代理的第三个条件
    public Object getInstance(Object object){
        //Enhancer是CGLIB的字节码增强器,可以很方便的对类进行拓展,如为类设置Superclass。

        //创建加强器,用来创建动态代理类
        Enhancer enhancer = new Enhancer();

        //这一步就是告诉chlib,生成的子类需要继承哪个类
        //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
        enhancer.setSuperclass(object.getClass());

        //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
        enhancer.setCallback(this);

        //创建动态代理类对象并返回
        //第一步、生成源代码,也就是代理类的二进制字节码文件
        //第二步、加载二进制字节码,编译成class对象
        //第三步、加载到JVM中,并返回被代理对象
        return enhancer.create();
    }

    //实现MethodInterceptor,重写方法
    //同样是做了字节码重组这样一件事情
    //对于使用API的用户来说,是无感知的

    //obj cglib生成的代理对象   sub:cglib生成的代理对象,method:被代理对象方法,objects:方法入参,methodProxy:代理方法
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("我是媒婆:" + "得给你找个男的");
        System.out.println("开始进行海选");
        System.out.println("--------------------------------");
        //这个o的引用是由chlib new出来的
        //chlib new出来的对象,是被代理对象的子类(继承了自己写的那个类)
        //oop,在new子类之前,实际上默认先调用了我们super()方法的
        //new了子类的同时,必须先new出来父类,这就相当于是间接的持有我们父类的引用
        //子类重写了父类的所有方法
        //我们改变子类对象的某些属性,也就是改变了父类的某些对象

        //methodProxy.invokeSuper是代理类(子类)调用父类的方法
        //methodProxy.invoke是调用自己,也就是代理类的方法
        methodProxy.invokeSuper(obj,args);
        System.out.println("--------------------------------");
        System.out.println("如何合适就恋爱");

        return null;
    }
}

3、使用时,然后通过 代理类对象.getInstance(业务类对象) 返回一个动态代理类对象(它是业务类的子类,可以用业务类引用指向它)。最后通过动态代理类对象进行方法调用。

public static void main(String[] args){
        //创建业务类和代理类对象,
        // 然后通过  代理类对象.getInstance(业务类对象)  返回一个动态代理类对象(它是业务类的子类,可以用业务类引用指向它)。
        // 最后通过动态代理类对象进行方法调用。
        cglibPerson obj = (cglibPerson)new cglibMeipo().getInstance(new cglibPerson());
       obj.findLove();
    }

从代码看被代理的类无需接口即可实现动态代理,而CGLibProxy代理类需要实现一个方法拦截器接口MethodInterceptor并重写intercept方法,类似JDK动态代理的InvocationHandler接口,也是理解为回调函数,同理每次调用代理对象的方法时,intercept方法都会被调用,利用该方法便可以在运行时对方法执行前后进行动态增强。关于代理对象创建则通过Enhancer类来设置的,Enhancer是一个用于产生代理对象的类,作用类似JDK的Proxy类,因为CGLib底层是通过继承实现的动态代理,因此需要传递目标对象(如A)的Class,同时需要设置一个回调函数对调用方法进行拦截并进行相应处理,最后通过create()创建目标对象(如A)的代理对象,运行结果与前面的JDK动态代理效果相同。

JDK动态代理和chlib的区别

JDK的动态代理是通过接口来进行强制转换的
生成以后的代理对象,可以强制转换为接口

cglib的动态代理时通过生成一个被代理对象的子类,然后重写父类的方法
生成以后的对象,可以强制转换为被代理对象(也就是用自己写的类)
子类引用赋值给父类

你可能感兴趣的:(【程序人生】--,设计模式,【Java】--,技术类)