zoukankan      html  css  js  c++  java
  • JDKProxy与CGlibProxy

    Spring 使用动态代理技术实现AOP. spring AOP使用两种代理机制

      1.基于JDK代理

        JDK动态代理主要涉及两个类:Proxy和InvocationHandler,自定义实现InvocationHandler定义横切逻辑,并通过反射机制调用目标类代码,将横切逻辑和业务代码编织一起。

      Proxy通过InvocationHanbler动态创建某一接口实例,生成目标类代理对象。

      用一个接口模拟

    /**
     * ee
     *
     * @author MM
     * @create 2018-03-28 17:16
     **/
    public interface UserManage {
        void queryUser(String id);
    
        void addUser(String id, String name);
    }
    public class UserManagerImpl implements UserManage {
    
    
        @Override
        public void addUser(String id, String name) {
            System.out.println("新增用户:" + name);
        }
    
        @Override
        public void queryUser(String id) {
            System.out.println("查询用户:" + id);
        }
    }

        

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    /**
     * eee
     *
     * @author MM
     * @create 2018-03-28 17:18
     **/
    public class JDKProxyHandler implements InvocationHandler {
        //需要代理的目标对象
        private Object targetObject;
    
    
        public JDKProxyHandler(Object targetObject) {
            this.targetObject = targetObject;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //这里可以处理业务逻辑
            doService();
    
            return method.invoke(targetObject, args);
        }
    
        private void doService() {
            System.out.println("业务逻辑处理。。。");
        }
    
    }

      测试代码

        public static void main(String[] args) {
            UserManage targetObject = new UserManagerImpl();
    
            JDKProxyHandler handler = new JDKProxyHandler(targetObject);
         //创建代理对象第二个参数即表明了JDK动态代理只能对实现了接口的类生成代理,而不能针对类,如果直接用类会抛异常
            UserManage userManagerJDK = (UserManage)Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
                    targetObject.getClass().getInterfaces(), handler);
    
            userManagerJDK.addUser("tom", "test");
    
        }

      2.基于CGLib代理

        针对JDK动态代理只能对接口创建代理实例,CGLIb来弥补这一缺陷。CGLIb代理使用底层字节码技术,可以为类创建一个子类,在子类中采用方法拦截,去拦截父类方法的调用并织如横切逻辑。

      

    /**
     * sgg
     *
     * @author MM
     * @create 2018-03-28 17:22
     **/
    public class CGLibProxy implements MethodInterceptor {
    
        // CGLib需要代理的目标对象
        private Object targetObject;
    
        public Object getProxy(Object obj){
            this.targetObject = obj;
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(obj.getClass());
            enhancer.setCallback(this);
            return enhancer.create();
    
        }
    
        @Override
        public Object intercept(Object proxy, Method method, Object[] args,
                                MethodProxy methodProxy) throws Throwable {
            doService();
            return method.invoke(targetObject, args);
        }
    
        private void doService() {
            System.out.println("业务逻辑处理。。。");
        }
    }
        public static void main(String[] args) {
    
            UserManage userManager = (UserManage) new CGLibProxy()
                    .getProxy(new UserManagerImpl());
            userManager.addUser("tom", "test");
    
        }

     附上网上的总结:

    spring对aop的支持

      *如果目标对象实现了接口,默认情况下会采用jdk的动态代理实现aop
      * 如果目标对象实现了接口,可以强制使用cglib实现aop
      *如果目标对象没有实现了接口,必须采用cglib库,spring会自动在jdk动态代理和cglib之间转换


    如何强制使用cglib实现aop?
       * 添加cglib库,spring_home/cglib/*.jar
       * 在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
     
    jdk动态代理和cglib字节码生成的区别?
       * jdk动态代理只能对实现了接口的类生成代理,而不能针对类
       * cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
         因为是继承,所以该类或方法最好不要声明成final 

  • 相关阅读:
    uniapp 的组件 定义了 直接使用即可 。
    uniapp 关闭微信小程序的索引警告
    微信小程序 组件化开发 实现 导航分类文章 小程序
    微信小程序 向下滚动加载更多 和 上滑刷新的写法
    微信小程序 用 Pormise 封装 wx.request 请求
    ES6 再次学习 Promise语法(代码图解)
    Maven依赖排除及版本统一
    Maven依赖使用的范围
    SSM整合时的配置文件
    SSM整合时用到的maven依赖
  • 原文地址:https://www.cnblogs.com/gcm688/p/9156282.html
Copyright © 2011-2022 走看看