一、适用场景
下面先看一个代码示例:
public class ForumService {
private TransactionManager transManager;
private PerformanceMonitor pmonitor;
private TopicDao topicDao;
private ForumDao forumDao;
public void removeTopic(int topicId) throws RuntimeException{
//监控开始
pmonitor.start();
//事务开始
transManager.beginTransaction();
//业务逻辑处理
topicDao.removeTopic(topicId);
//事务结束
transManager.endTransaction();
//监控结束
pmonitor.end();
}
public void createForum(Forum forum) throws RuntimeException{
pmonitor.start();
transManager.beginTransaction();
//业务逻辑处理
forumDao.create(forum);
transManager.endTransaction();
pmonitor.end();
}
}
如上面的代码所示,监控的代码和业务逻辑代码耦合到了一起,而且通过上面的实现方式,每一个需要监控的代码,在业务逻辑处理开始之前和之后都需要加入监控开始(pmonitor.start();)和监控结束(pmonitor.end();)的代码。
这样做的存在如下几个缺点:
1.监控代码嵌入到了业务逻辑当中,后续需要加上监控模块的代码都需要这么改;
2.造成了大量的重复代码。
因此需要考虑将重复性的监控代码给抽取出来,而AOP为抽取这类重复性的代码提供了很好的解决方案。如下图所示,AOP将分散到各个业务逻辑中的重复代码抽取到一个独立模块中,这样就可以保持业务代码独立,逻辑清晰。
合适通过AOP完成横切逻辑的应用场景如下所示:
- 性能检测
- 访问控制
- 事务管理
- 日志记录
二、AOP术语
- 连接点(Joinpoint)
- 程序执行的某个特定位置(如方法前后,异常抛出时等)
- 可以在连接点处执行增强逻辑
- Spring只支持方法的连接点
- 方法调用前
- 方法调用后
- 方法抛出异常时
- 切点(Pointcut)
- 每个程序都可以有多个连接点,如一个类有两个方法,这两个方法都是切点
- AOP通过“切点”定位连接点
- 一个切点可以匹配多个连接点
- 一个方法为一个切点
- 方法的调用前/后,抛出异常时为连接点
- 增强(Advice)
- 织入目标类连接点上的一段代码
- 织入目标类连接点上的一段代码
注:一般Spring所提供的增强接口都是带有方位名的,如BeforeAdvice、AfterReturningAdvice、ThrowsAdvice。所以一般只有结合切点和增强,才能确定特定的连接点并实施增强逻辑。
-
目标对象(Target)
- 增强逻辑的织入目标类
如下图所示,在AOP的帮助下,FormService只实现了非横切的程序业务逻辑,而性能监控以及事务管理这些横切逻辑可以使用AOP动态的织入特定的连接点上。
- 增强逻辑的织入目标类
-
引介(Introduction)
- 一种特殊的增强,它为类添加一些属性和方法
- 即使一个业务类原本未实现某个接口,通过AOP的引介功能也可以动态地为业务类添加接口的实现逻辑,让业务类成为这个接口的实现类
-
织入(Weaving)
- 将增强添加到目标类的具体连接点上的过程
- AOP织入方式如下所示
- 编译器织入:要求使用特殊的Java编译器
- 类装载期织入:要求使用特殊的类装载器
- 动态代理织入:在运行期为目标类添加增强生成的子类的方式(Spring采用)
-
代理(Proxy)
- 一个类被AOP织入增强之后,就产生了一个结果类,它是融合了原类和增强逻辑的代理类
-
切面(Aspect)
- 由切点和增强组成
三、AOP主要工作
AOP的主要作用就是将增强应用于目标对象的连接点上,主要涉及如下两个工作:
- 如何通过切点将增强定位到连接点上
- 如何在增强中编写切面的代码
参考资料
《精通Spring 4.x企业应用开发实战》