Java动态代理

一、概念

       代理模式是一种设计模式,能够在不修改源目标的前提下,额外扩展源目标的功能。即通过访问源目标的代理类,再由代理类去访问源目标。这样一来,要扩展功能,就无需修改源目标的代码了。只需要在代理类上增加就可以了。

        常见的代理分为:静态代理和动态代理。  至于两者之间的区别和优劣势,通过接下来的代码进行演示。

二、静态代理

 要求:在某个类执行类中方法时,添加日志信息

1、定义接口

public interface Calculate {

    public int add(int a,int b);

}

2、定义实现类

public class Calculator implements Calculate{
    @Override
    public int add(int a, int b) {
        System.out.println(a+b);
        return a+b;
    }
}

3、定义代理类

public class CalculatorWithLog implements Calculate{

    Calculator calculator = new Calculator();

    public CalculatorWithLog (Calculator calculator){
        this.calculator = calculator;
    }

    @Override
    public int add(int a, int b) {
        System.out.println("增强执行前日志");
        int res = calculator.add(a,b);
        System.out.println("增强执行后日志");
        return res;
    }
}

4、测试

    public static void main(String[] args) {

        Calculator calculator = new Calculator();
        Calculate withLog = new CalculatorWithLog(calculator);
        withLog.add(1, 3);
    }

 Java动态代理_第1张图片

 总结:

静态代理在实际使用过程中,会存在如下问题:

  • 对于每一个目标类均需要编写相应的代理类,对于大量目标类编写对应的代理类不切实际
  • 当接口改变时,所有的代理类和目标类均需要改变,耦合过深

 二、动态代理

        动态代理指在程序运行过程中,使用JDK的反射机制,创建代理对象,并动态指定代理的目标类 ,使用JDK反射包下的Proxy和InvocationHandler实现代理对象的动态创建。

1、Proxy类

        动态代理中最核心的一个类,使用静态方法newProxyInstance(),创建代理对象,其方法入参包含:

  • ClassLoader loader:类加载器,负责向内存中加载对象,需要使用对应目标对象的类加载器
  • Class[] interfaces:目标对象实现的接口
  • InvocationHandler invocation:自定义代理类需要实现的功能,返回值为代理对象

2、InvocationHandler接口

         接口中仅实现一个方法:invoke(),自定义代理类需要增强的功能在此方法中实现。

即invoke()方法中需要完成的功能:

  • 调用目标类方法
  • 功能增强,在目标方法调用前后,增加功能

3、动态代理示例 

1、定义接口

同理静态代理部分

2、定义实现类

同理静态代理部分

3、创建InvocationHandler实现类,实现代理方法

public class MyInvocationHandler  implements InvocationHandler {

    private Object target = null;

    public MyInvocationHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        Object res = method.invoke(target,args);
        System.out.println("代理增强!!");
        return res;
    }
}

其中,target对象为代理的目标对象

4、Proxy类创建代理对象,并通过接口类型调用方法

public static void main(String[] args) {

        Calculator calculator = new Calculator();
        InvocationHandler invocationHandler = new MyInvocationHandler(calculator);
        Calculate x = (Calculate) Proxy.newProxyInstance(calculator.getClass().getClassLoader(),
                calculator.getClass().getInterfaces(),
                invocationHandler );
        x.add(1,3);
    }

Java动态代理_第2张图片

 总结:

       相较于静态代理,动态代理可在不改变目标方法功能的前提下,完成代理功能增强,即在实际应用中,用于在不修改目标方法的基础上,增强不满足要求的方法。

你可能感兴趣的:(代理模式)