什么是spring Aop
AOP(Aspect-OrientedProgramming,面向切面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
而AOP技术则恰恰相反,它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。
使用“横切”技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。Aop 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。正如Avanade公司的高级方案构架师Adam Magee所说,AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离。”
实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。
如何使用spring Aop
我们经常会用到的有如下几种
1、基于代理的AOP
2、纯简单Java对象切面
3、@Aspect注解形式的
4、注入形式的Aspcet切面
开发步骤:
I. 创建原始对象
II. 添加额外功能(Advice、MethodInterceptor)
III. 切入点(PointCut)
IV. 组装切面
spring Aop应用场景
场景一:Aop与事务
使用基于注解的AOP事务管理
<tx:annotation-driven transaction-manager="transactionManager"/>
<aop:aspectj-autoproxy />
探索tx:annotation-driven标签:
<tx:annotation-driven/>标签是注解驱动的事务管理支持的核心。
<tx:annotation-driven/>标签的属性:
transaction-manager:指定到现有的PlatformTransactionManager bean的引用,通知会使用该引用。default="transactionManager"
mode:指定Spring事务管理框架创建通知bean的方式。可用的值有proxy和aspectj。前者是默认值,表示通知对象是个JDK代理;后者表示Spring AOP会使用AspectJ创建代理。
order:指定创建的切面的顺序。只要目标对象有多个通知就可以使用该属性。
proxy-target-class:该属性如果为true就表示你想要代理目标类而不是bean所实现的所有接口。default="false"
探索@Transactional注解:
你可以指定传播、隔离级别、超时以及允许和不允许的异常。
@Transactional注解的属性:
propagation:指定事务定义中使用的传播
isolation:设定事务的隔离级别
timeout:指定事务的超市(秒)
readOnly:指定事务的超时
noRollbackFor:目标方法可抛出的异常所构成的数组,但通知仍会提交事务
rollbackFor:异常所构成的数组,如果目标方法抛出了这些异常,通知就会回滚事务
基于注解的事务管理小结:
如果定义在类上,那么所有的方法都使用相同的方式,有些read就会抱怨给太多的东西了。
如果在每个方法上都定义注解,那么就会很麻烦。
(可以使用XML AOP事务管理能更好的处理这种情况)
场景二:Aop与日志
使用AspectJ框架对操作日志进行记录
场景三:Aop与缓存
1 . 获取到拦截方法的 @Cache 注解,并生成缓存 key;
2 . 通过缓存 key,去缓存中获取数据;
3 . 如果缓存命中,执行如下流程:
- 如果需要自动加载,则把相关信息保存到自动加载队列中;
- 否则判断缓存是否即将过期,如果即将过期,则会发起异步刷新;
- 最后把数据返回给用户。
4 . 如果缓存没有命中,执行如下流程:
-
- 选举出一个 leader 回到数据源中去加载数据,加载到数据后通知其它请求从内存中获取数据(拿来主义机制);
- leader 负责把数据写入缓存;如果需要自动加载,则把相关信息保存到自动加载队列中;
- 最后把数据返回给用户。
缓存是用于解决高并发场景下系统的性能及稳定性问题的。