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

    为什么需要代理?
    在不修改被代理类代码的条件下,可以对被代理类中的方法进行想要的处理,如添加日志,记录方法运行时间(testNG就有此功能,未修改我们的测试代码,却可以统计每个方法的运行时间)
     
    从静态代理作为理解的入口:
    何为静态代理?
    可对应生活中的,hr统计测试岗位人员信息交给人事部主管。
      首先创建一个Person接口,约束个人信息统计的方法:
    public interface Person {
        void giveMessage();
        void fun();
    }
    

      创建员工类:

    package day03;
    
    public class Employee implements Person{
        String name;
        Employee(String name){
            this.name = name;
        }
    
        public void giveMessage(){
            System.out.println("give Message");
        }
    
        public void fun(){
            System.out.println("other fun");
        }
    }

      创建员工代理类,相当于hr类:

    public class EmployeePro implements Person{
        Employee employee;
        EmployeePro(Employee employee){
            this.employee = employee;
        }
    
    
        public void giveMessage(){
            System.out.println("add logs");
            System.out.println("give Message");
    
        }
    
        public void fun(){
            System.out.println("add logs");
            System.out.println("other fun");
        }
    
    }
    View Code

     测试下:

    public class Test {
        public static void main(String[] args) {
            Employee employee = new Employee("Claire");//创建被代理人
            EmployeePro employeePro = new EmployeePro(employee);//创建代理人对象
            employeePro.giveMessage();//通过代理人来执行相应方法
        }
    }
    View Code

    运行结果:

    思考:
    1.员工类中有2个方法,添加日志的代码就写了2遍,造成代码重复。
     
    2.如果要统计开发岗位人员信息交给人事主管呢,又要怎么做?
    需要再创建开发岗位的代理类,重写方法并添加日志。
    以上缺点很明显:需要手动创建多个代理类,并且添加日志的功能重复N遍。
     
    动态代理便很好的解决了该问题,下面是动态代理的实现方式:
     
    创建一个类实现InvocationHandler:
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    //该类使用泛型,可以支持作为任何类的InvocationHandler,如果不理解,可以直接写成非泛型
    public class MyInvocationHandler<T> implements InvocationHandler {
        T target;//需要关联的被代理对象,这里将代理与被代理关联起来
        MyInvocationHandler(T target){
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("add log");//在方法执行之前添加日志
            Object result = method.invoke(target, args);//这里是通过反射调用target对象的method方法,参数是args
            return result;
        }
    }
    View Code

    测试下:

    import java.lang.reflect.Proxy;
    
    public class ProxyTest {
        public static void main(String[] args) {
            //创建被代理人
            Person employee = new Employee("claire");
            //创建代理对象
            Person employeePro = (Person) Proxy.newProxyInstance(ProxyTest.class.getClassLoader(), new Class<?>[]{Person.class}, new MyInvocationHandler<Person>(employee));
            //代理对象执行相应方法
            employeePro.giveMessage();
            employeePro.fun();
        }
    }
    View Code

    测试结果是:

    我们还可以使用匿名类的方式来实现,代码就更简洁了,如下:

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class ProxyTestAnonymous {
        public static void main(String[] args) {
            Person employee = new Employee("claire");
            Person emplPro = (Person) Proxy.newProxyInstance(ProxyTestAnonymous.class.getClassLoader(), new Class<?>[]{Person.class}, new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("add logs");//方法调用前添加日志
                    Object result = method.invoke(employee, args);
                    return result;
                }
            });
    
            emplPro.fun();
            emplPro.giveMessage();
        }
    }
    View Code

    以上我们就使用动态代理解决了上面提出的问题。

    但是可以发现,Java自带动态代理,被代理类必须有对应的实现接口,这就比较受限了。

  • 相关阅读:
    python 玩转列表list
    Python入门之_水仙花数
    自兴人工智能 字符串
    自兴人工智能 元组
    自兴人工智能 列表
    自兴人工智能 python特点了解
    python走迷宫
    (自兴人工智能) python 元组
    (自兴人工智能) 玩转 python 字符串
    (自兴人工智能)Python 列表(List)的灵活使用
  • 原文地址:https://www.cnblogs.com/clairejing/p/12921780.html
Copyright © 2011-2022 走看看