很多的开源框架底层都用了java动态代理的技术,所以想要看懂框架源码,这些基础的东西先要搞清楚。
类图:
Interface和implement分别是我们原有的业务代码的接口和实现,现在我们想给原有代码加一些功能,而又不想动原有的逻辑。比如说加打印日志或者安全过滤功能。可以实现一个日志的代理对象或者安全代理对象,在所有用到原对象的地方都采用代理对象,就可以实现对原对象附加功能而不改变其内容的目的了。
举个具体例子:
假设原有代码 InterfaceA.java
public interface InterfaceA {
public void sayHi();
}
以及他的实现类 A.java
public class A implements InterfaceA {
@Override
public void sayHi() {
System.out.println("Hi");
}
}
假如现在需要在这个sayHi方法之前打印日志。
新建LoggingInvocationHandler.java类实现打印日志的功能(虽然只是打印了Logging。。。。。。)
public class LoggingInvocationHandler implements InvocationHandler {
private Object target;
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("Logging 。。。 。。。");
return method.invoke(target, args);
}
public LoggingInvocationHandler setTarget(Object target) {
this.target = target;
return this;
}
}
新建LogginProxy.java来创建代理类
public class LoggingProxy {
public static Object getProxy(Object target){
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new LoggingInvocationHandler().setTarget(target));
}
}
这个InvocationHandler和Proxy都是jdk为我们实现好了的可以方便我们创建代理。
测试代码:
public class Main {
public static void main(String[] args) {
InterfaceA a = (InterfaceA)LogProxy.getProxy(new A());
a.sayHi();
}
}
输出结果:
Logging:。。。 。。。
Hi
总结:Spring框架管理的Bean都是基于代理的,Mybatis插件、缓存功能也是动态代理实现的,理解动态代理有助于看懂这些框架的源代码,慢慢总结,继续努力!