spring(二) aop和事务

aop

面向切面编程,可以将业务代码和功能代码分开,比如日志打印和权限控制等等,避免重复代码和解耦。通过动态代理,运行期修改字节码信息,实现字节码增强,根据原有类生成代理类。

aop定义

切入点 pointcount
哪个方法,哪个类切入
通知 advice
切入的内容
切面 aspect
切入点+通知
advior 另一种切面
切入点+通知,advisor只持有一个Pointcut和一个advice,而aspect可以多个pointcut和多个advice
weaving 织入
将切面加入到对象中,创建出代理对象

aspactJ框架的注解
spring对配置aspectJ的注解的类进行处理,为所有切入点织入功能代码。

  • @Aspect 指定为切面类
  • @Pointcut 指定切入点
  • @Around 指定在方法前后通知
  • @Before 指定在方法前通知
  • @After 指定在在方法后通知
spring生成代理类原理

spring的aop基于动态代理,那么spring源码时怎么根据原对象生成代理对象,放到spring容器中的?这个就涉及到BeanPostProcessor接口,通过实现这个接口,在bean创建后,会遍历所有实现了这个接口的类,进行bean的加工。而spring提供的aop注解的实现同样如此,通过AbstractAutoProxyCreator类实现了BeanPostProcessor

AbstractAutoProxyCreator类
该类通过获取bean容器中所有实现了Advisor接口的类,放到ProxyFactory类中进行生成代理类,对符合的切入点进行增加增强代码。获取所有实现了Advisor的类,相当于一次返回一个得到了各种增强的代理类。如果不通过这种方式,而是每个都是去实现BeanPostProcessor更改生成的bean,为该bean生成代理类,那么就需要多次生成代理类,显然是不合理的。

多个代理类的代理顺序
根据实现了order接口决定。spring的事物注解的order值是int最大值,优先级最低

切面执行顺序

通过@Order(1)注解或者实现order类,指定执行顺序,数字越小越优先执行。

源码:ReflectiveAspectJAdvisorFactory

spring 事务

spring 提供 @Transactional 注解提供给开发者方便的开启事务和提交事务。

使用位置
可用与类上和方法上,可用于接口上、实现类上。用于类上即相当于给类中的所有方法都加上事务处理。被修饰的方法需要是public的,否则不会生效。

使用方式
注入DataSourceTransactionManager类,配置事务管理器的数据源,事务管理器将通过这个数据源获取连接。
spring项目可以通过xml中配置tx:annotation-driven开启事务,soringboot可以通过@EnableTransactionManagement注解开启事务。

原理
事务的处理也是通过aop的形式,声明了BeanFactoryTransactionAttributeSourceAdvisor类,实现了Advisor接口。切入点通过类上和方法上的注解,匹配是否包含Transactional注解,符合的话则取出注解上的属性,为当前的bean创建代理对象。符合后
最终的事务处理源码在TransactionInterceptor::invoke

spring事务传播行为
  • required : 如果当前有事务就支持当前事务,没有事务就新建事务。默认隔离级别
  • support : 如果当前有事务就支持当前事务,没有事务就已非事务形式执行
  • mandaytory : 如果当前有事务就支持事务,没有事务就抛出异常
  • required_new : 每次都新建一个事务,如果已经存在事务就将当前事务挂起再新建
  • not_support : 不支持事务,存在事务就将事务挂起
  • never : 如果当前存在事务就抛出异常
  • nested : 如果当前有存在事务就嵌套执行

处理隔离级别的源码
AbstractPlatformTransactionManager::getTransaction方法。

一个事务方法调用另一个事务方法,怎么拿到同一个数据库连接?

逻辑在源码DataSourceTransactionManager::doGetTransaction中。
通过TransactionSynchronizationManager类,用ThreadLocal存储一个map,map的key是数据源datasource对象,也就是创建事务管理器时赋值的对象。map的value为ConnectionHolder对象,该对象包含数据库连接Connection和当前事务状态transactionActive

也就是说,spring将连接等事务相关信息放到threadlocal类,当调用另一个事务方法时,另一个事务方法会从threadlocal取出当前事务信息。

什么时候取threadlocal中的事务信息?什么时候把连接放到ConnectionHolder中?什么时候把ConnectionHolder放到TransactionSynchronizationManager中?
AbstractPlatformTransactionManager::getTransaction方法中,一开始先通过doGetTransaction获取threadlocal中的事务信息,获取后进行事务隔离级别判断(比如如果级别是mandaytory,则如果缓存中没有事务信息就报错)。之后会调用doBegin方法,事务信息不存在的话会通过datasource获取连接,将连接封装到ConnectionHolder类,关闭事务自动提交,如果设置了readOnly则会执行SET TRANSACTION READ ONLY,还有设置事务超时时间等。最后将ConnectionHolder放到threadlocal中。

简单的说就是会先去ThreadLocal取出事务信息,开始事务时会把事务信息放到threadlocal中

自定义aop怎么控制织入在事务处理前或者事务处理后

通过实现Ordered类,重写getOrder方法返回排序值实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值