2017-08-20 by yunqing.wen
笔者读了《spring in action 4th Edition》第四章后,结合自身理解谈谈面向切面编程,聊做笔记,同时也希望能带领读者快速了解AOP。
1. AOP是啥?
在计算机科学中,面向切面编程(AOP,aspect-oriented programming),是一种通过将散布于应用中多处的系统级通用关注点(如日志、安全、事务等)和具体业务逻辑分离来提高软件的模块化的编程范式。
下面解释下相关的术语:
横切关注点(cross-cutting concern),是系统中散步于多处的需要关注的通用型的功能。所谓通用是指,这样的功能并非某个模块中特有的,而是横跨多个模块的。举个例子,如果我们要统计系统中某些对象所有方法在一段时间内的调用次数,以便找出热点方法,那么,毫无疑问,我们需要在调用这些方法前做些统计上的工作。这样的统计上的工作是横切关注点,这是因为,首先是通用型的功能(统计方法调用次数),与方法中具体业务逻辑是不相干的;其次是“横切”的,要关注的“某些对象”会散步于多个系统模块中。
通知(advice),定义了某个关注点中要完成的工作及在何时执行这个工作。以统计方法调用次数为例,通知包含两个部分,一个是要完成的工作,即在原先统计的数值上加上1(调用时加1),另一个是在什么时机执行,这里即在调用方法前。
切点(pointcut),定义了在系统执行过程中将通知应用到何处。如果说通知定义了横切关注点的what和when,那么切点则定义了where。以统计调用次数为例,切点可以是一个负责用户登录服务对象的某个方法。
切面(aspect),等于通知+切点,定义了如何将横切关注点应用到系统的全部。
织入(weaving),把切面应用到目标对象并创建新的代理对象的过程。在目标对象的生命周期里有多个点可以织入:编译期、类加载期、运行期。
2.AOP有啥好处?
为什么要使用AOP呢?一句话来说,通过将横切关注点和业务逻辑分离,我们能得到更好的模块化,更清晰的设计方案,更优雅易扩展的代码。
3.在spring中使用AOP
在spring中,AOP是通过在运行时把切面织入到spring管理的bean中。Spring只支持方法级别的切点。其他如AspectJ和JBoss,除了方法切点,还支持字段和构造器切点。
下面介绍在spring中具体如何使用AOP。
首先给出一个业务逻辑的接口,之后我们基于这个接口的方法定义切面。
```
public interface SomeLogic {
public void someConcreteLogicMethod(int intArgument);
}
```
下面介绍如何基于注解使用AOP:
```
@Aspect
public class StatisticWork {
private int count = 0;
@Pointcut("execution(* somePackagePath.someConcreteLogicMethod(int))" + " && args(intArgument) ")
public void someConcreteLogicMethod(int intArgument){}
@Before
public void countInvocation(int intArgument) {
System.out.println("IntArgument is " + intArgument);
count++;
}
}
```
配置文件:
```
@Configuration
@EnableAspectJAutoProxy
public class TestConfig {
@Bean
public SomeLogic someLogic() {
return new SomeLogicImpl();
}
@Bean
public StatisticWork statisticWork() {
return new StatisticWork();
}
}
```
此外,还可以通过注解在原先接口的基础上增加新的方法,而不需要修改原来的代码,实现非侵入性。这主要是通过代理拦截调用并委托给实现该方法的其他对象来实现的。
如:
```
public inerface AdditioanalLogic {
public void additionalLogicMethod();
}
```
在配置文件中,应这样写:
```
@Aspect
public class AdditioanalLogicIntroducer {
@Declareparents(value="somePackagePath.AdditioanalLogic+", defaultImpl=DefaultAdditioanalLogicImpl.class)
public static AdditioanalLogic additioanalLogic;
}
```
基于XML使用AOP,和基于注解的方式大同小异。值得注意的是,当无法或不能修改通知类的代码时,只能使用基于XML使用AOP。具体如何使用,可参考《Spring in Action 4th Edition》第四章。