zoukankan      html  css  js  c++  java
  • java动态代理

    java动态代理有2种实现,JdkDynamicAopProxy和Cglib2AopProxy。

    spring的AOP是都用到了这2中实现,jdk动态代理是由java内部的反射机制来实现的,用ProxyGenerator.generateProxyClass(...,...)来生成字节码,cglib动态代理则是生成一个代理类的子类(所以final类是不可以动态代理的),底层则是借助asm来实现的。总的来说,反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。还有一点必须注意:jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。由此可以看出,jdk动态代理有一定的局限性,cglib这种第三方类库实现的动态代理应用更加广泛,且在效率上更有优势。

    Jdk动态代理 

    原理剖析见: http://www.cnblogs.com/MOBIN/p/5597215.html

    package com.amigo.study.DynamicProxyDemo;
    
    /**
     * Created by moi on 2017/10/1.
     */
    public interface IDbService {
        public String getDBName();
    
    }
    package com.amigo.study.DynamicProxyDemo;
    
    /**
     * Created by moi on 2017/10/1.
     */
    public class DBServiceImpl implements IDbService {
    
        @Override
        public String getDBName() {
            System.out.println("db name is amigo.");
            return "amigo";
        }
    }
    package com.amigo.study.DynamicProxyDemo;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    /**
     * Created by moi on 2017/10/1.
     */
    public class DBServiceInvokeHandler implements InvocationHandler {
        private Object target;
    
        DBServiceInvokeHandler() {
            super();
        }
    
        DBServiceInvokeHandler(Object target) {
            super();
            this.target = target;
        }
      

          /**
          * 动态代理的目的往往是要增强被代理类,这里就是增强逻辑的放置位置。
          * @param proxy
          * @param method
          * @param args
          * @return
          * @throws Throwable
          */

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if ("getDBName".equals(method.getName())) {
                System.out.println("++++++before " + method.getName() + "++++++");
                Object result = method.invoke(target, args);
                System.out.println("++++++after " + method.getName() + "++++++");
                return result;
            } else {
                Object result = method.invoke(target, args);
                return result;
            }
        }
    }
    package com.amigo.study.DynamicProxyDemo;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    
    /**
     * Created by moi on 2017/10/1.
     */
    public class DynamicProxyTest {
        public static void main(String[] args) {
            // 这里是保存下来生成的.class文件。 注意:要在工程根目录新建/com/sun/proxy的目录,要不会报错。
            System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
            JDKDynamicProxyTest();
        }
    
        public static void JDKDynamicProxyTest() {
            IDbService iDbService = new DBServiceImpl();
            InvocationHandler invocationHandler = new DBServiceInvokeHandler(iDbService);
            IDbService userServiceProxy = (IDbService) Proxy.newProxyInstance(iDbService.getClass().getClassLoader(),
                    iDbService.getClass().getInterfaces(), invocationHandler);
            System.out.println(userServiceProxy.getDBName());
        }
    }

     Cglib动态代理

    package com.amigo.study.DynamicProxyDemo;
    
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    /**
     * Created by moi on 2017/10/1.
     */
    public class DBServiceMethodInterceptor implements MethodInterceptor {
    
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("Before:" + method);
            Object object = methodProxy.invokeSuper(o, objects);
            System.out.println("After:" + method);
            return object;
        }
    }
    package com.amigo.study.DynamicProxyDemo;
    
    import net.sf.cglib.proxy.Enhancer;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    
    /**
     * Created by moi on 2017/10/1.
     */
    public class DynamicProxyTest {
        public static void main(String[] args) {
            //        JDKDynamicProxyTest();
            CglibDynamicProxyTest();
        }
    
        public static void JDKDynamicProxyTest() {
            IDbService iDbService = new DBServiceImpl();
            InvocationHandler invocationHandler = new DBServiceInvokeHandler(iDbService);
            IDbService userServiceProxy = (IDbService) Proxy.newProxyInstance(iDbService.getClass().getClassLoader(),
                    iDbService.getClass().getInterfaces(), invocationHandler);
            System.out.println(userServiceProxy.getDBName());
        }
    
        public static void CglibDynamicProxyTest(){
            Enhancer enhancer = new Enhancer();
         // 设置被代理类 enhancer.setSuperclass(DBServiceImpl.
    class);
         // 回调函数用于增强被代理类 enhancer.setCallback(
    new DBServiceMethodInterceptor()); DBServiceImpl dbService = (DBServiceImpl)enhancer.create(); dbService.getDBName(); } }
  • 相关阅读:
    C# 使用消息队列,包括远程访问
    Python3中urllib使用与源代码
    多年前写的DataTable与实体类的转换
    DataTable添加列和行的三种方法
    DevExpress 常用命令包括导出-打印-打印预览等
    c#开发_Dev的关于XtraGrid的使用(GridControl小结)
    正则表达式精华(包涵常用经典方法)
    数据库 插入时 碰到NULL报错判断的一种方法(技巧)
    MDI窗体简单方法(调用,闪屏)
    GridControl GridView 修改表格中的标题居中
  • 原文地址:https://www.cnblogs.com/parkin/p/7617623.html
Copyright © 2011-2022 走看看