美文网首页一起学JDK源码
源码基础 -- 动态代理(2)

源码基础 -- 动态代理(2)

作者: Kinsanity | 来源:发表于2018-10-11 10:39 被阅读1次

    再看java动态代理之Cglib动态代理,早期大家选择Cglib主要是因为Cglib底层采用ASM字节码生成框架,运行效率要比使用JDK原生代理高。

    Cglib动态代理实现

        //1.定义一个被代理类(cglib是生成被代理类的一个子类,不能直接用接口)
        public class SayHi {
            public void sayHi(String name){
                System.out.println("hi: " + name);
            }
        }
        //2..实现代理方法(实现MethodInterceptor接口),创建代理类
        public class SayHiCglib implements MethodInterceptor{
    
        private Object target;//业务类对象,供代理方法中进行真正的业务方法调用
    
        //相当于JDK动态代理中的绑定,创建代理对象
        public Object getInstance(Object target) {  
            this.target = target;  //给业务对象赋值
            Enhancer enhancer = new Enhancer(); //创建加强器,用来创建动态代理类
            enhancer.setSuperclass(this.target.getClass());  //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
            //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
            enhancer.setCallback(this); 
           // 创建动态代理类对象并返回  
           return enhancer.create(); 
        }
        // 实现回调方法,实现代理方法
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { 
            System.out.println("before method...");
            proxy.invokeSuper(obj, args); //调用业务类(父类中)的方法
            System.out.println("after method...");
            return null; 
        }
    }
    //3.测试
    public class CglibTest {
        public static void main(String[] args) {
            SayHi sayHi = new SayHi();
            SayHiCglib cglib = new SayHiCglib();
            SayHi sayHiProx = (SayHi) cglib.getInstance(sayHi);
            sayHiProx.sayHi("z3");
        }  
    }
    

    可以看出来实现起来很简单,主要的是要学会代理这种思想,用这种方式去解决工作中具体遇到的问题。

    Cglib与JDK动态代理比较

    JDK动态代理是通过接口中的方法名,在动态生成的代理类中调用业务实现类的同名方法;
    CGlib动态代理是通过继承业务类,生成的动态代理类是业务类的子类,通过重写业务方法进行代理;
    JDK和Cglib都是在运行期生成字节码,JDK是直接写Class字节码,Cglib使用ASM框架写Class字节码。
    JDK调用代理方法,是通过反射机制调用,Cglib是通过FastClass机制直接调用方法。

    注意事项

    使用Cglib动态代理除了要引用cglib本身的jar包还需要引入asm的jar包,因为Cglib底层采用ASM字节码生成框架。
    Cglib采用的是继承,所以不能使用final对被代理类进行修饰。

    相关文章

      网友评论

        本文标题:源码基础 -- 动态代理(2)

        本文链接:https://www.haomeiwen.com/subject/zaovaftx.html