静态代理
场景1 :
记录登陆时间,注册时间:
public class UserController {
private MetricsCollector metricsCollector;
public UserVo login(String telephone,String passwd){
long startTimeStamp = System.currentTimeMillis();
// log in logic
long endTimeStamp = System.currentTimeMillis();
long loginTime = endTimeStamp - startTimeStamp;
metricsCollector.recordRequest(loginTime);
}
public UserVo register(String telephone, String passwd) {
long startTimeStamp = System.currentTimeMillis();
// register logic
long endTimeStamp = System.currentTimeMillis();
long loginTime = endTimeStamp - startTimeStamp;
metricsCollector.recordRequest(loginTime);
return userVo;
}
}
显然新加入记录时间功能 加入了原有的逻辑中,对之后的拓展加大了阻碍.
通过定义接口:
public interface IUserController {
public UserVo login(String telephone,String passwd)
public UserVo register(String telephone,String passwd)
}
让UserController , UserControllerProxy 都实现IUserController.
public class UserController implements IUserController{
@Override
public UserVo login(String telephone,String passwd){
// log in logic
return userVO;
}
@Override
public UserVo register(String telephone, String passwd) {
// register logic
return userVo;
}
}
public class UserControllerProxy implements IUserController{
private UserController controller;
private MetricsCollector metricsCollector;
public UserControllerProxy(UserController userController){
this.controller = userController;
this.metricsCollector = new MetricsCollector();
}
@Override
public UserVo login(String telephone, String passwd) {
long startTimeStamp = System.currentTimeMillis();
//origin logic
UseVo useVo = this.controller.login(telephone,passwd);
long endTimeStamp = System.currentTimeMillis();
long loginTime = endTimeStamp - startTimeStamp;
this.metricsCollector.recordRequest(loginTime);
return null;
}
@Override
public UserVo register(String telephone, String passwd) {
long startTimeStamp = System.currentTimeMillis();
//origin logic
UseVo useVo = this.controller.register(telephone,passwd);
long endTimeStamp = System.currentTimeMillis();
long registerTime = endTimeStamp - startTimeStamp;
this.metricsCollector.recordRequest(registerTime);
return null;
}
}
在调用的时候通过代理调用:
IUserController userController = new UserControllerProxy(new UserController());
达到的尽量少的改动原来的代码目的.
注: 在这里我们给加多了一个接口 IUserController,但是如果原来的UserController 是一个第三方的类,我们不能修改. 那么我们就要通过继承并且重写相应的方法 来实现代理了
public class UserControllerProxy1 extends UserController{
private MetricsCollector metricsCollector;
public UserControllerProxy1(){
this.metricsCollector = new MetricsCollector();
}
@Override
public UserVo login(String telephone, String passwd) {
long startTimeStamp = System.currentTimeMillis();
//origin logic
UseVo useVo = super.login(telephone,passwd);
long endTimeStamp = System.currentTimeMillis();
long loginTime = endTimeStamp - startTimeStamp;
this.metricsCollector.recordRequest(loginTime);
return useVo;
}
@Override
public UserVo register(String telephone, String passwd) {
long startTimeStamp = System.currentTimeMillis();
//origin register
UseVo useVo = super.register(telephone,passwd);
long endTimeStamp = System.currentTimeMillis();
long registerTime = endTimeStamp - startTimeStamp;
this.metricsCollector.recordRequest(registerTime);
return useVo;
}
}
如果附加功能只有一个还好,要是有多个就需要些很多代理类,并且实现一些方法这样子以来有增加了成本.
应用的场景: 监控,统计,限流,事物 日志.
JAVA 的动态代理 Spring 底层AOP 就是通过动态代理来实现的.
public class MetricsCollectorProxy {
private MetricsCollector metricsCollector;
public MetricsCollectorProxy(){
this.metricsCollector = new MetricsCollector();
}
public Object createProxy(Object proxyObject){
Class<?>[] interfaces = proxyObject.getClass().getInterfaces();
DynamicProxyHandler handler = new DynamicProxyHandler(proxyObject);
return Proxy.newProxyInstance(proxyObject.getClass().getClassLoader(),interfaces,handler);
}
class DynamicProxyHandler implements InvocationHandler{
private Object proxyObject;
DynamicProxyHandler(Object proxyObject){
this.proxyObject = proxyObject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long startTimeStamp = System.currentTimeMillis();
// register
method.invoke(proxyObject,args);
long endTimeStamp = System.currentTimeMillis();
long loginTime = endTimeStamp - startTimeStamp;
metricsCollector.recordRequest(loginTime);
return null;
}
}