引介增强实例需求
在前面我们已经提到了前置、后置、环绕、最终、异常等增强形式,它们的增强对象都是针对方法级别的,而引介增强,则是对类级别的增强,我们可以通过引介增强为目标类添加新的属性和方法,更为诱人的是,这些新属性或方法是可以根据我们业务逻辑需求而动态变化的。怎么来理解这一点?我们先展示一个用引介增强解决的现实需求问题,现在先来看看我们的一个需求:
我们要设计一个定时任务,在每天特定流量高峰时间里,判断人们某个网络请求在服务端程序业务逻辑处理上的耗时,一般地,我们web后端处理请求处理按如下时序图执行:
现在,即需要我们统计从接收请求后到发出相应前这个过程的耗时。
最直接的解决方法就是,在Controller层的每一个方法起始到结束,分别记录一次时间,用结束减起始来获得结果,但这存在两个问题:
- 根据springMVC一个方法对应一种请求,如果我们的controller中有很多方法,而我们需要为每一个方法都进行统计,这意味者我们需要在controller中嵌入大量重复冗杂的代码,并且这些代码和我们controller层逻辑没有任何关系,如果日后我们根据需求要添加其他任务,就又要修改我们的controller,这不符合开闭原则和职责分明原则。
- 因为我们的需求是动态的,我们还可能需要在controller中每次调用都去判断当前时刻是否处于需要统计耗时的时刻。
基于接口实现和代理工厂
下面看看我们如何用引介增强来解决同样的问题:
1. 定义UserController
public class UserController {
public void login(String name){
System.out.println("I'm "+name+" ,I'm logining");
try {
Thread.sleep(100);//模拟登陆过程中进行了数据库查询。各种业务逻辑处理的复杂工作
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
2. 配置引介增强需要实现的代理接口
public interface TaskActiver {
//通过此接口来监控是是否激活定时器任务
void startTask();//满足特定条件,开启任务
void stopTask();//不满足特定条件,停止任务
}
3. 配置我们的增强实现类
/*
1. DelegatingIntroductionInterceptor是引介增强接口IntroductionInterceptor的实现类,我们通过扩展此接口自定义引介增强类
2. 引介增强类要实现我们的代理接口TaskActiver,这是和其他增强不同的地方。
*/
public class MyTaskController extends DelegatingIntroductionInterceptor implements TaskActiver{
private ThreadLocal<Boolean> isTime =