代理模式是一种设计模式,能够在不修改源目标的前提下,额外扩展源目标的功能。即通过访问源目标的代理类,再由代理类去访问源目标。这样一来,要扩展功能,就无需修改源目标的代码了。只需要在代理类上增加就可以了。
常见的代理分为:静态代理和动态代理。 至于两者之间的区别和优劣势,通过接下来的代码进行演示。
要求:在某个类执行类中方法时,添加日志信息
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);
}
总结:
静态代理在实际使用过程中,会存在如下问题:
动态代理指在程序运行过程中,使用JDK的反射机制,创建代理对象,并动态指定代理的目标类 ,使用JDK反射包下的Proxy和InvocationHandler实现代理对象的动态创建。
动态代理中最核心的一个类,使用静态方法newProxyInstance(),创建代理对象,其方法入参包含:
接口中仅实现一个方法:invoke(),自定义代理类需要增强的功能在此方法中实现。
即invoke()方法中需要完成的功能:
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);
}
总结:
相较于静态代理,动态代理可在不改变目标方法功能的前提下,完成代理功能增强,即在实际应用中,用于在不修改目标方法的基础上,增强不满足要求的方法。