ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

JDK 动态代理 和 cgLib动态代理

2022-07-14 23:34:44  阅读:128  来源: 互联网

标签:JDK 代理 System canWrite println new 动态 out


1 spring 动态代理的一些说明

 

  1 spring 5.0 默认使用的 代理方式 依旧是 jdk 动态代理(之前的版本也是)


  2 springboot 2.X 开始 默认使用代理方式 cglib(springboot 2.X 默认使用 spring 5,给人的感觉是 spring 5.0 开始默认使用的 cglib 代理)


  3 可以使用 spring.aop.proxy-target-class=false 切换成 jdk 动态代理(spring boot 默认是true),spring xml 方式使用 <aop:aspectj-autoproxy proxy-target-class="true"/>


  4 spring aop默认使用的代理方式是 jdk 代理 的意思是,有父类接口的就使用jdk 动态代理,没有的还是只能使用 cglib

 

 

2 jdk 动态代理 Proxy 例子(通过 Proxy.newProxyInstance 得到实例)

    /**
     * jdk 动态代理
     */
    @Test
    public void t1(){
        ReadWriteInfo writeInfo = new ReadWriteInfo();
        writeInfo.setInfo("我的信息");


        InvocationHandler renterHandler = new InvocationHandler(){
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("代理类参数:" + proxy.getClass() );
                System.out.println("调用的方法名字:" + method.getName() );
                System.out.println("参数:" + JSONObject.toJSONString( args ) );

                return method.invoke(writeInfo,args);
            }
        };

        CanRead canRead = (CanRead)Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{CanRead.class, CanWrite.class},renterHandler);
        CanWrite canWrite = (CanWrite)canRead;

        System.out.println("代理类:" + canWrite.getClass() );
        System.out.println("代理类的接口:" + JSONObject.toJSONString( canWrite.getClass().getAnnotatedInterfaces() ) );
        System.out.println("代理类类型判断 CanRead :" +  (canWrite instanceof   CanRead) );
        System.out.println("代理类类型判断 CanWrite:" +  (canWrite instanceof   CanWrite) );
        System.out.println("代理类类型判断 ReadWriteInfo:" +  (canWrite instanceof   ReadWriteInfo) );

        System.out.println( canRead.getInfo( 1L  ));
        canWrite.setInfo( "新的信息" );
        System.out.println(   canRead.getInfo( 1L  ) );

        logger.info("取到的goods 名字:{}", "1111111111" );
    }

  

 

 

3 cglib Enhancer 动态代理 例子(通过 Enhancer.create 得到代理类)

  值得注意的是,可以指定多个 增强实现,但是多个增强实现的时候必须指定 拦截器 ,返回使用的增强逻辑下标

    /**
     *   cgLib 的 动态代理
     */
    @Test
    public void t2(){
        ReadWriteInfo writeInfo = new ReadWriteInfo();
        writeInfo.setInfo("我的信息");

        org.springframework.cglib.proxy.InvocationHandler renterHandler = new org.springframework.cglib.proxy.InvocationHandler(){
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("代理类参数:" + proxy.getClass() );
                System.out.println("调用的方法名字:" + method.getName() );
                System.out.println("参数:" + JSONObject.toJSONString( args ) );

                return method.invoke(writeInfo,args);
            }
        };
        org.springframework.cglib.proxy.InvocationHandler renterHandler2 = new org.springframework.cglib.proxy.InvocationHandler(){
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("代理类参数2:" + proxy.getClass() );
                System.out.println("调用的方法名字2:" + method.getName() );
                System.out.println("参数2:" + JSONObject.toJSONString( args ) );

                return method.invoke(writeInfo,args);
            }
        };


        CallbackFilter callbackFilter = new CallbackFilter() {
            @Override
            public int accept(Method method) {
                return 1;
            }
        };


        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass( writeInfo.getClass() );
        enhancer.setCallbacks(new Callback[]{renterHandler,renterHandler2});
        enhancer.setCallbackFilter(callbackFilter );

        ReadWriteInfo rwInfo = (ReadWriteInfo) enhancer.create();

        logger.info("代理类信息:{}", rwInfo.getClass() );
        rwInfo.getInfo(1L);
        rwInfo.setInfo( "new  info" );
        rwInfo.getInfo(1L);

    }

 

 

 

 

4 java静态代理实现

    /**
     * 静态代理
     */
    @Test
    public void t3(){
        ReadWriteInfo writeInfo = new ReadWriteInfo();
        writeInfo.setInfo("我的信息");


        StaticProxy staticProxy = new StaticProxy();
        staticProxy.inti(writeInfo,writeInfo);

        staticProxy.setInfo("静态代理信息");
        System.out.println( staticProxy.getInfo(1L) );
    }

    /**
     * 静态代理类
     */
    class StaticProxy implements CanRead,CanWrite {
        private  CanRead canRead ;
        private  CanWrite canWrite;

        public void inti( CanRead canRead ,CanWrite canWrite ){
            this.canRead = canRead;
            this.canWrite = canWrite;
        }

        @Override
        public String getInfo(Long id) {
            System.out.println("静态代理工作getInfo......");
            return canRead.getInfo(id);
        }

        @Override
        public void setInfo(String info) {
            System.out.println("静态代理工作setInfo......");
            canWrite.setInfo(info);
        }
    }

  

5 动态代理和静态代理的区别:

  

  1 动态代理和静态代理的区别在于 代理类是硬编码产生的还是通过 java 反射产生的

  2 动态代理的优势有两个 第一是代理类动态产生,第二是增强的逻辑动态替换

  3 静态代理 如果使用 InvocationHandler 接口也可以实现 增强逻辑的动态替换,但是不能实现代理类的动态生成

  4 代理类的动态生指的是 不需要硬编码就能实现一个包含一个或者多个接口的代理实现类,这是动态代理最大的优势

  5 当前调用方法名字 可以通过当前线程 调用记录得到 Thread.currentThread().getStackTrace()[1]

  6 单个类指定代理模式可以通过设置 BeanDifination的 proxyTargetClass 属性来设置 definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);

 

 

6 动态的获取当前 执行方法的方法名

  

    /**
     * 获取当前调用的方法名字
     * Thread.currentThread().getStackTrace() 里面有当前调用的调用栈追踪记录
     * Thread.currentThread().getStackTrace()[0]  是追踪方法本身, Thread.currentThread().getStackTrace()[1] 是当前方法
     *
     */
    @Test
    public void t4(){
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();

        logger.info("获取当前方法的名字:{}",methodName );
        logger.error("当前占信息:{}", JSONObject.toJSONString( Thread.currentThread().getStackTrace() ) );
    }

  

 

标签:JDK,代理,System,canWrite,println,new,动态,out
来源: https://www.cnblogs.com/cxygg/p/16479767.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有