zoukankan      html  css  js  c++  java
  • 浅谈Java代理二:Cglib动态代理-MethodInterceptor

     浅谈Java代理二:Cglib动态代理-MethodInterceptor

    CGLib动态代理特点

    使用CGLib实现动态代理,完全不受代理类必须实现接口的限制,而且CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。

    示例业务逻辑:

    1-有一个明星叫胡歌(class HuGe)

    3-找明星做事情需要经过助理(ProxyFactory )

    4-如果要找胡歌唱歌、演戏,需要先找助理,然后助理去找胡歌唱歌、演戏(class testProcyFactory)

    1-被代理类(没有实现任何接口)

    package com.huishe.testOfSpring.methodinterceptor;
    
    public class HuGe {
    
        public void sing(String song) {
            System.out.println("胡歌演唱: " + song);
        }
    
        public String act(String teleplay) {
            System.out.println("胡歌决定出演电视剧: " + teleplay);
            return "胡歌答应出演电视剧: " + teleplay;
        }
    }

    2-代理工厂(即创建代理的通用写法)

    package com.huishe.testOfSpring.methodinterceptor;
    
    import java.lang.reflect.Method;
    
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    public class ProxyFactory implements MethodInterceptor{
        //要代理的原始对象
        private Object object;
        
        //1-创建代理对象
        public Object createProcy(Object target){
            this.object = target;
            //1-Enhancer类是CGLib中的一个字节码增强器,它可以方便的对你想要处理的类进行扩展
            Enhancer enhancer=new Enhancer();  
            //2-将被代理类HuGe设置成父类
            enhancer.setSuperclass(this.object.getClass());  
            //3-设置拦截器
            enhancer.setCallback(this);  
            //4-动态生成一个代理类
            Object objProxy = enhancer.create();  
            
            return objProxy;
            
        }
        
        //2-实现MethodInterceptor的intercept方法
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("before: " + method);
            //调用proxy.invoke()方法,会报java.lang.StackOverflowError错误,原因是invoke()内部会一直被反复调用
            //Object object = proxy.invoke(obj, args);
            Object object = proxy.invokeSuper(obj, args);
            System.out.println("after: " + method);
            return object;
        }
    }

     3-进行测试

    package com.huishe.testOfSpring.methodinterceptor;
    
    import org.junit.Test;
    
    import net.sf.cglib.proxy.Enhancer;
    
    public class cglibMethodInterceptorTest {
    
        @Test
        public void testProcyFactory(){
            //1-实例化需要被代理的类
            HuGe huGe = new HuGe();
            //2-实例化代理工厂
            ProxyFactory cglibProxy = new ProxyFactory();
            //3-动态生成一个代理类,并从Object强制转型成父类型HuGe
            HuGe hg =(HuGe)cglibProxy.createProcy(huGe);
            
            //4-执行动态代理类的方法
            hg.sing("逍遥叹");
            hg.act("琅琊榜");
            
        }
        
    }

     4-测试结果

    日志输出:
    
    before: public void com.huishe.testOfSpring.methodinterceptor.HuGe.sing(java.lang.String)
    胡歌演唱: 逍遥叹
    after: public void com.huishe.testOfSpring.methodinterceptor.HuGe.sing(java.lang.String)
    before: public java.lang.String com.huishe.testOfSpring.methodinterceptor.HuGe.act(java.lang.String)
    胡歌决定出演电视剧: 琅琊榜
    after: public java.lang.String com.huishe.testOfSpring.methodinterceptor.HuGe.act(java.lang.String)

    参考资料

    1-https://blog.csdn.net/jiaotuwoaini/article/details/51675684
    2-https://www.cnblogs.com/writeLessDoMore/p/6973853.html

  • 相关阅读:
    zabbix5.0安装
    Ubuntu下为服务器添加新用户
    oss存储的安装与使用
    模型结构可视化
    GPU算力查询
    台式机PC挂载共享盘
    Python批量拷贝文件
    NVIDIA显卡驱动,CUDA,CUDNN安装流程
    使用Docker GPU训练环境安装过程中所碰到的问题
    Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
  • 原文地址:https://www.cnblogs.com/wobuchifanqie/p/9996978.html
Copyright © 2011-2022 走看看