作为spring最大的两个特点AOP与DI,其实也可以看做多种设计模式的组合。
1.AOP 是什么
AOP:面向切面编程。(通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。--百度百科)。
先介绍一下简单的思路,所以举个例子。假设一个业务流程,去图书馆借书,以及还书
可以注意到,验证身份信息是两者的共同流程,我们可以将它单独剥离出来,在两个流程中复用。这样的代码复用就是AOP?不是的。换个角度理解,如果拿出了验证身份的流程,那么我们就能专注于单一功能的业务流程进行实现,比如借书的逻辑,还书的逻辑。AOP本质上就是将主要流程分离出来,然后将验证身份等等并不是那么主要的逻辑剥离。可以单独实现主要逻辑,之后再将通用的逻辑插入相应的位置。而这个位置就是所谓的切片。
这么看来这东西还是很简单,如果想在一般的java代码里实现,只需要采用工厂模式,或者装饰器模式就可以实现。但是这仅仅只是介绍了它的一个特点,也就是切片,在更加贴近实际的情况下,模块化开发也能达到上面的效果。
对于单个功能的开发我们习惯放在一个类当中,比如借书,还书。但是如果我们想要在借书还书的过程当中打印各种日志呢?当然,我可以将代码写到各个流程的开始,亦或是结束的位置,但是对于单个的类而言他们的存在一定程度上造成了功能的耦合,毕竟我想要借书,关你打印日志什么事。
情况如下:
很明显,借书其实就一步= =,但是这日志会在他的开始,结束时产生,这时候就显现出AOP的好处了,我们可以在借书开始,结束,过程中切出各种切片,然后在切片中放入相应的逻辑处理(也许是日志打印,也许是别的),这就将借书这样的逻辑进一步的松耦合,而且切片的内容高度自定义,可以根据各自的需求定义出不同的逻辑。这也提高了代码的灵活性。
2.spring 中的 AOP
spring中的拦截器就是aop模式的一种实行。
拦截器代码如下
- preHandle是在接收到请求时,但是还没处理请求时调用
- postHandle请求结束时调用
- afterCompletion视图渲染完成调用
public class TestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request
, HttpServletResponse response, Object handler) {
System.out.println("请求执行前");
return true;//只有返回true之后的方法才会执行
}
@Override
public void postHandle(HttpServletRequest request
, HttpServletResponse response, Object handler
, ModelAndView modelAndView) {
System.out.println("请求结束");
}
@Override
public void afterCompletion(HttpServletRequest request
, HttpServletResponse response, Object handler
, Exception ex) {
System.out.println("视图渲染完成");
}
}
然后添加一下请求拦截器
@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new TestInterceptor())
.addPathPatterns("/**");//url路径匹配模式
super.addInterceptors(registry);
}
}
之后访问匹配的url,结果如下