• Spring笔记06(Spring AOP的底层实现动态代理)


    1.代理模式readMe:

    代理设计模式: 是java中常用的设计模式!
    
       特点:
           01.委托类和代理类有相同的接口或者共同的父类!
           02.代理类为委托类负责处理消息,并将消息转发给委托类!
           03.委托类和代理类对象通常存在关联关系!
              一个代理类对象与一个委托类对象关联!
           04.代理类本身并不是真正的实现者!而是通过调用委托类的方法,
              来实现功能!
    
    
       按照代理类创建的时机,代理类分为两种:
       01.静态代理:由我们程序猿或者特定的工具自动生成了源代码,
                     在程序运行之前,.class文件已经存在了!
          (serviceImpl 调用了 dao层的方法! 真正的实现是Dao)
       02.动态代理:在程序运行期间,通过反射的方式动态的创建出来!
    
    
       按照我们的使用方式:  是由共同的接口还是公共的父类?
    
         01.jdk动态代理 (接口)
              必须知道一个类和一个接口
               001.InvocationHandler接口只有一个方法
    
                public Object invoke(Object proxy, Method method, Object[] args)
                       throws Throwable;
    
               proxy:代理类对象
               method:被代理的方法
               args:被代理的方法的参数列表
    
              002.Proxy 类:
               public static Object newProxyInstance(ClassLoader loader,
                      Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException
                  loader:类加载器
                  interfaces:代理类实现的所有接口
                  h:InvocationHandler接口的一个实例   this当前对象
                     因为我们想使用jdk动态代理 必须是 代理类 实现 InvocationHandler!
                      它让我们传递父接口 我们传递 自身!
    
         02.cglib动态代理(接口+父类)
             必须知道一个类和一个接口
               001.MethodInterceptor接口
    
               public Object intercept(Object obj,
                  Method method,Object[] args,MethodProxy proxy) throws Throwable;
    
            intercept是所有拦截器执行的方法,类似于jdk动态代理中的invoke
    
    
              002. Enhancer类
    
               设置委托类和代理类的公共接口或者公共的父类
               public void setSuperclass(Class superclass) {
                      if (superclass != null && superclass.isInterface()) {
                          setInterfaces(new Class[]{ superclass });
                      } else if (superclass != null && superclass.equals(Object.class)) {
                          // affects choice of ClassLoader
                          this.superclass = null;
                      } else {
                          this.superclass = superclass;
                      }
                  }
    
                   代理类执行完毕 通知委托类
                   public void setCallback(final Callback callback) {
                          setCallbacks(new Callback[]{ callback });
                      }
    
    
                    在Enhancer类的父类AbstractClassGenerator中有一个方法
                      创建我们需要的代理类
                      protected Object create(Object key)

    2.静态代理:

    01.接口代码:

    package cn.pb.dao;
    
    /**
     * 动物类 父接口
     */
    public interface Animal {
        //主业务
        void eat();
        void sleep();
    }

    02.实现类代码:

    package cn.pb.dao.impl;
    /**
     * 狗狗类 实现了Animal接口
     */
    
    import cn.pb.dao.Animal;
    
    public class Dog implements Animal {
        public void eat() {
            System.out.println("狗狗在啃骨头!");
        }
    
        public void sleep() {
            System.out.println("狗狗在午休!");
        }
    }

    03.静态代理类:

    package cn.pb.staticproxy;
    
    import cn.pb.dao.Animal;
    import cn.pb.dao.impl.Dog;
    
    /**
     * 狗狗的静态代理类
     */
    public class AnimalStaticProxy implements Animal {
    
        private Dog dog;
    
    
        public void sleep() {
            System.out.println("主人在召唤");  //系统级业务
            dog.sleep();
            System.out.println("主人离开"); //系统级业务
        }
    
        public void eat() {
            System.out.println("主人在召唤"); //系统级业务
            dog.eat();
            System.out.println("主人离开"); //系统级业务
        }
    
        public Dog getDog() {
            return dog;
        }
    
        public void setDog(Dog dog) {
            this.dog = dog;
        }
    
    
        /**
         * 我们发现的问题
         * 01:代码冗余
         * 02:把冗余的代码提取成公共的方法
         * 03:有可能小猫咪也有这些方法
         * 04:提取成一个工具类中的方法
         * 05:现在有一个小猫咪 也需要执行 sleep和eat 以及系统级业务方法
         * 06:我们又得创建一个小猫咪对应的代理类
         * 07:动物有很多  ,难道需要我们创建N个代理类吗??肯定!
         */
    }

    04.测试类代码:

     /**
         * 静态代理的测试方法
         */
        @Test
        public void testStaticProxy(){
            AnimalStaticProxy proxy = new AnimalStaticProxy();
            Dog dog=new Dog();
            proxy.setDog(dog);
    
    
            proxy.eat();
            System.out.println("*************");
            proxy.sleep();
        }

    3.JDK动态代理:

    01.接口代码:

    package cn.pb.dao;
    
    /**
     * 动物类 父接口
     */
    public interface Animal {
        //主业务
        void eat();
        void sleep();
    }

    02.实现类代码:

    package cn.pb.dao.impl;
    /**
     * 狗狗类 实现了Animal接口
     */
    
    import cn.pb.dao.Animal;
    
    public class Dog implements Animal {
        public void eat() {
            System.out.println("狗狗在啃骨头!");
        }
    
        public void sleep() {
            System.out.println("狗狗在午休!");
        }
    }

    03.动态代理类代码:

    package cn.pb.jdkdynamicproxy;
    /**
     * JDK的动态代理类
     */
    
    import cn.pb.dao.Animal;
    import cn.pb.dao.impl.Dog;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class AnimalJdkDynamicProxy implements InvocationHandler {
    
        /**
         *  01.我们不确定委托类是谁?委托类的类型 是Object
         *   和委托类建立关联关系
         */
        private Object target;
    
    
        /**
         * 02.给我一个委托类,我返回一个代理类对象
         */
        public Object createProxy(Object target){
            //根据传递的参数 进行对象的关联
            this.target=target;
            return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(), this);
        }
    
        /**
         *
         * @param proxy :代理对象
         * @param method :方法名
         * @param args : 参数列表
         * @return
         */
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("主人在召唤"); //系统级业务   开始事务
            Object result= method.invoke(target,args);  // 主业务
            System.out.println("主人离开"); //系统级业务     日志处理  关闭事务
            return result;
        }
    
    
        //创建测试方法
        public static void main(String[] args) {
            AnimalJdkDynamicProxy proxy=new AnimalJdkDynamicProxy();
            Animal dog= (Animal) proxy.createProxy(new Dog());
            dog.eat();
            System.out.println("**************************");
            dog.sleep();
    
        }
    }

    04.测试代码:

     @Test
        public void testJdkDynamicProxy(){
            AnimalJdkDynamicProxy proxy=new AnimalJdkDynamicProxy();
            Animal dog= (Animal) proxy.createProxy(new Dog());
            dog.eat();
            System.out.println("**************************");
            dog.sleep();
        }

    4.cglib动态代理:

    01.接口代码:

    package cn.pb.dao;
    
    /**
     * 动物类 父接口
     */
    public interface Animal {
        //主业务
        void eat();
        void sleep();
    }

    02.实现类代码:

    package cn.pb.dao.impl;
    /**
     * 狗狗类 实现了Animal接口
     */
    
    import cn.pb.dao.Animal;
    
    public class Dog implements Animal {
        public void eat() {
            System.out.println("狗狗在啃骨头!");
        }
    
        public void sleep() {
            System.out.println("狗狗在午休!");
        }
    }

    03.动态代理类代码:

    package cn.pb.cglibdynamicproxy;
    
    
    /**
     * Cglib动态代理
     */
    import cn.pb.dao.Animal;
    import cn.pb.dao.impl.Dog;
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    public class AnimalCglibDynamicProxy implements MethodInterceptor {
    
        /**
         * 在enhancer中有一个setCallBack(this)
         * 这样就实现了代理类和委托类的关联
         */
        private Enhancer enhancer=new Enhancer();
    
        /**
         *  创建代理类对象
         */
        public  Object  createProxy(Class clazz){
            //设置公共的接口或者公共的类
            enhancer.setSuperclass(clazz);
            //建立关联关系
            enhancer.setCallback(this);
            return enhancer.create();
        }
    
        /**
         * 类似于我们jdk中的invoke
         */
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("主人在召唤"); //系统级业务   开始事务
            Object result= proxy.invokeSuper(obj,args);  // 主业务
            System.out.println("主人离开"); //系统级业务     日志处理  关闭事务
            return result;
        }
    
    
        //创建测试方法
        public static void main(String[] args) {
            AnimalCglibDynamicProxy proxy=new AnimalCglibDynamicProxy();
            //这里的参数可以传三种形式01:new Dog().getClass()
            // 02:Class.forName("cn.pb.dao.impl.Dog") 03.Dog.class
            Animal dog= (Animal) proxy.createProxy(new Dog().getClass());
            dog.eat();
            System.out.println("**************************");
            dog.sleep();
        }
    }

    04.测试代码:

      @Test
        public void testCglibDynamicProxy(){
            AnimalJdkDynamicProxy proxy=new AnimalJdkDynamicProxy();
            Animal dog= (Animal) proxy.createProxy(new Dog());
            dog.eat();
            System.out.println("**************************");
            dog.sleep();
        }
  • 相关阅读:
    Ubuntu 更换软件源
    Ubuntu 配置 SOCKS5
    Ubuntu 配置 Sha-dow-socks
    frp(内网穿透)
    solr 远程代码执行(CVE-2019-12409)
    多线程处理爬虫
    python实现文件自动排序
    python 实现根据文件名自动分类移动至不同的文件夹
    Centos7如何开启任意端口服务
    centos7默认安装没有连接网络
  • 原文地址:https://www.cnblogs.com/lyb0103/p/7658581.html
Copyright © 2020-2023  润新知