Spring——Spring AOP1(代理模式Proxy)
作者:mmseoamin日期:2024-02-05

代理(Proxy)模式

1.创建工程

Spring——Spring AOP1(代理模式Proxy),第1张

2.代理(Proxy)模式介绍

  • 作用:通过代理可以控制访问某个对象方法,在调用这个方法前做前置处理,调用这个方法后做后置处理。(即: AOP的微观实现!)

  • Spring——Spring AOP1(代理模式Proxy),在这里插入图片描述,第2张

  • 核心角色

    • 抽象角色(接口):定义公共对外方法

    • 真实角色(周杰伦):实现抽象角色,定义真实角色所要实现的业务逻辑,

    • 代理角色(代理人):实现抽象角色,是真实角色的代理,通过调用真实角色的方法来完成业务逻辑,并可以附加自己的操作。

      Spring——Spring AOP1(代理模式Proxy),第3张

      3.静态代理

      3.1.抽象角色
      package com.wt.proxy.StaticProxy;
      public interface Star {
      	/**
      	 * 面谈
      	 */
      	void confer();
      	/**
      	 * 签合同
      	 */
      	void signContract();
      	/**
      	 * 订票
      	 */
      	void bookTicket();
      	/**
      	 * 唱歌
      	 */
      	void sing();
      	/**
      	 * 收钱
      	 */
      	void collectMoney();
      }
      
      3.2.真正角色(周杰伦)
      package com.wt.proxy.StaticProxy;
      public class RealStar implements Star {
      	public void bookTicket() {
      	}
      	public void collectMoney() {
      	}
      	public void confer() {
      	}
      	public void signContract() {
      	}
      	public void sing() {
      		System.out.println("RealStar(周杰伦本人).sing()");
      	}
      }
      
      3.3.代理角色(经纪人)
      package com.wt.proxy.StaticProxy;
      public class ProxyStar implements Star {
      	
      	private Star star;
      	
      	public ProxyStar(Star star) {
      		super();
      		this.star = star;
      	}
      	public void bookTicket() {
      		System.out.println("ProxyStar.bookTicket()");
      	}
      	public void collectMoney() {
      		System.out.println("ProxyStar.collectMoney()");
      	}
      	public void confer() {
      		System.out.println("ProxyStar.confer()");
      	}
      	public void signContract() {
      		System.out.println("ProxyStar.signContract()");
      	}
      	public void sing() {
      		star.sing();
      	}
      }
      
      3.4.测试
      package com.wt.proxy.StaticProxy;
      public class Client {
      	public static void main(String[] args) {
      		Star proxy = new ProxyStar(new RealStar());
      		
      		proxy.confer();
      		proxy.signContract();
      		proxy.bookTicket();
      		proxy.sing();
      		
      		proxy.collectMoney();
      		
      	}
      }
      
      3.5.静态代理的缺点
      1. 代理类和实现类实现了相同的接口,这样就出现了大量的代码重复。
      2. 代理对象只服务于一种类型的对象。如果要服务多类型的对象,例如代码是只为UserService类的访问提供了代理,但是还要为其他类如DeptService类提供代理的话,就需要我们再次添加代理DeptService的代理类。

      4.jdk动态代理

      4.1.抽象角色
      public interface Star {
          /**
           * 唱歌
           */
          void sing();
      }
      
      4.2.真正角色(周杰伦)
      package com.wt.JdkProxy;
      //真实角色(周杰伦)
      public class RealStar implements Star {
          //优点:此时代码不再重复
          public void sing() {
              System.out.println("周杰伦:快使用双截棍,哼哼哈嘿....");
          }
      }
      
      4.3.代理角色(经纪人)
      package com.wt.JdkProxy;
      import java.lang.reflect.InvocationHandler;
      import java.lang.reflect.Method;
      import java.lang.reflect.Proxy;
      //代理类工厂
      public class ProxyFactory {
          //优点:此时可以代理任意类型的对象
          //真实角色(周杰伦)
          private Object realObj;
          public ProxyFactory(Object realObj) {
              this.realObj = realObj;
          }
          //获得代理对象
          public Object getProxyObject(){
              /**
               * Proxy:作用创建代理对象
               *      ClassLoader loader:类加载器
               *      Class[] interfaces:真实角色实现的接口,根据接口生成代理类
               *      InvocationHandler h:增强的逻辑,即如何代理(宋吉吉要做的事)
               */
              return Proxy.newProxyInstance(
                      realObj.getClass().getClassLoader(),
                      realObj.getClass().getInterfaces(),
                      new InvocationHandler() {
                          /**
                           *
                           * @param proxy:代理类,一般不用
                           * @param method:要调用的方法
                           * @param args:调用方法时的参数
                           * @return
                           * @throws Throwable
                           */
                          public Object invoke(Object proxy, Method method, Object[] args)
                              											throws Throwable {
                              System.out.println("真正的方法执行前!");
                              System.out.println("面谈,签合同,预付款,订机票");
                              Object result = method.invoke(realObj, args);
                              System.out.println("真正的方法执行后!");
                              System.out.println("收尾款");
                              return result;
                          }
                      }
              );
          }
      }
      
      4.4.测试
      public class Client {
          public static void main(String[] args) {
              //获得代理对象
              Star proxyObject = (Star) new ProxyFactory(new RealStar()).getProxyObject();
              System.out.println(proxyObject.getClass());//class com.sun.proxy.$Proxy0
              proxyObject.sing();
          }
      }
      

      5.Cglib动态代理

      cglib与动态代理最大的区别就是:

      • 使用jdk动态代理的对象必须实现一个接口
      • 使用cglib代理的对象则无需实现接口

        CGLIB是第三方提供的包,所以需要引入jar包的坐标:

        
            cglib
            cglib
            2.2.2
        
        

        如果你已经有spring-core的jar包,则无需引入,因为spring中包含了cglib。

        5.1.真正角色
        package com.wt.proxy.CglibProxy;
        public class RealStar{
        	public void sing() {
        		System.out.println("RealStar(周杰伦本人).sing()");
        	}
        }
        
        5.2.代理角色(经纪人)
        package com.wt.proxy.CglibProxy;
        import org.springframework.cglib.proxy.Enhancer;
        import org.springframework.cglib.proxy.MethodInterceptor;
        import org.springframework.cglib.proxy.MethodProxy;
        import java.lang.reflect.Method;
        //代理工厂
        public class ProxyFactory implements MethodInterceptor {
            //真实角色
            private Object realObj;
            public ProxyFactory(Object realObj) {
                this.realObj = realObj;
            }
            /**'
             * 获得子类代理对象
             * @return
             */
            public Object getProxyObject() {
                //工具类
                Enhancer en = new Enhancer();
                //设置父类
                en.setSuperclass(realObj.getClass());
                //设置回调函数
                en.setCallback(this);
                //创建子类代理对象
                return en.create();
            }
            /*
                在子类中调用父类的方法
                    intercept方法参数说明:
                        obj : 代理对象
                        method : 真实对象中的方法的Method实例
                        args : 实际参数
                        methodProxy :代理对象中的方法的method实例
             */
            public Object intercept(Object obj, Method method, Object[] args, 
                                    	MethodProxy methodProxy)throws Throwable {
                System.out.println("真正的方法执行前!");
                System.out.println("面谈,签合同,预付款,订机票");
                Object result = method.invoke(realObj, args);
                System.out.println("真正的方法执行后!");
                System.out.println("收尾款");
                return object;
            }
        }
        
        5.3.测试
        package com.by.proxy.CglibProxy;
        //测试类
        public class Client {
            public static void main(String[] args) {
                //获取代理对象
                RealStar proxyObject = 
                    (RealStar) new ProxyFactory(new RealStar()).getProxyObject();
                proxyObject.sing();
            }
        }