Java代理

1. 代理模式和静态代理

1.1 代理模式

  • Proxy Pattern,23个经典模式的一种,又称委托模式
  • 为目标对象提供(包装)了一个代理,这个代理可以控制对目标对象的访问
    • 外界不用直接访问目标对象,而是访问代理对象,由代理对象再调用目标对象
    • 代理对象中可以添加监控和审查处理

1.2 静态代理

  • Java代理:静态代理和动态代理
  • 静态代理
    • 代理对象持有目标对象的句柄
    • 所有调用目标对象的方法,都调用代理对象的方法,可以在方法的实现前后进行前置处理和后置处理
    • 对每个方法,需要静态编码(理解简单,但代码繁琐)

2. 动态代理

  • 静态代理

    对每个方法,都需要静态编码,简洁但繁琐

  • 动态代理

    对目标对象的方法每次被调用,进行动态拦截

  • 代理处理器

    • 持有目标对象的句柄
    • 实现InvocationHandler接口
      • 实现invoke方法
      • 所有的代理对象方法调用,都会转发到invoke方法
      • invoke的形参method,就是指代理对象方法的调用
      • 在invoke内部,可以根据method,使用目标对象不同的方法来响应请求
  • 代理对象

    • 根据给定的接口,由Proxy类自动生成的对象
    • 类型com.sun.proxy.$Proxy0,继承自java.lang.reflect.Proxy
    • 通常和目标对象实现同样的接口(可另实现其他的接口)
    • 实现多个接口
      • 接口的排序非常重要
      • 当多个接口里面有方法同名,则默认以第一个接口的方法调用
  • 示例

    // 接口
    public interface Subject{
        public void request();
    }
    
    // 目标对象
    class SubjectImpl implements Subject{
      public void request(){
          System.out.println("I am dealing the request.");
      }
    }
    
    // 代理类的调用处理器
    class ProxyHandler implements InvocationHandler{
        private Subject subject;
        public ProxyHandler(Subject subject){
            this.subject = subject;
        }
        
        //此函数在代理对象调用任何一个方法时都会被调用。
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
        	System.out.println(proxy.getClass().getName());
        	//定义预处理的工作,当然你也可以根据 method 的不同进行不同的预处理工作
            System.out.println("====before====");
            Object result = method.invoke(subject, args);
            System.out.println("====after====");
            return result;
        }
    }
    
    // 动态代理模式
    public class DynamicProxyDemo {
        public static void main(String[] args) {
        	//1.创建目标对象
        	SubjectImpl realSubject = new SubjectImpl();    
        	
        	//2.创建调用处理器对象
        	ProxyHandler handler = new ProxyHandler(realSubject); 
        	
        	//3.动态生成代理对象
            Subject proxySubject = 
            		(Subject)Proxy.newProxyInstance
            		  (SubjectImpl.class.getClassLoader(),
                       SubjectImpl.class.getInterfaces(), handler); 
            //proxySubject真实类型com.sun.proxy.$Proxy0
            //proxySubject继承Proxy类,实现Subject接口
            //newProxyInstance的第二个参数,就是指定代理对象的接口
            
            //4.客户端通过代理对象调用方法
            //本次调用将自动被代理处理器的invoke方法接收
            proxySubject.request();    
            
            System.out.println(proxySubject.getClass().getName());
            System.out.println(proxySubject.getClass().getSuperclass().getName());
        }
    }
    

3. AOP编程

3.1 AOP: Aspect Oriented Programming

  • 面向切面编程(vs 面向对象编程)

    • 面向对象:将需求功能划分为不同的、独立、封装良好的类,并让它们通过继承和多态实现相同和不同的行为。

    • 面向切面:将通用需求功能从众多类中分离出来,使得很多类共享一个行为,一旦发生变化,不必修改很多类,而只需要修改这个行为即可。

      image-20220814125010463

  • 面向切面编程

    • 分离代码的耦合(高内聚,低耦合)
    • 业务逻辑变化不需要修改源代码/不用重启
    • 加快编程和测试速度
    • 一个概念/规范,没有限定语言
    • 不是取代OOP编程,而是OOP的补充,和数据库的触发器有点详细
  • 主要内容

    • Aspect:配置文件,包括一些PointCut和相应的Advice
    • Joint point:在程序中明确定义的点,如方法调用、对类成员访问等
    • Pointcut:一组joint point,可以通过逻辑关系/通配符/正则等组合起来,定义了相应advice将要发生的地方
    • Advice:定义了在pointcut处要发生的动作,通过before/after/arount来关联
    • Weaving:advice代码在具体joint point的关联方式
posted @ 2022-07-18 23:20  hunter-w  阅读(379)  评论(0编辑  收藏  举报