代理对象在哪里创建
先从bean被创建后如何产生代理对象开始,在AbstractAutowireCapableBeanFactory.doCreateBean
初始化bean创建后,并且将依赖注入到bean中,在调用initializeBean 方法对刚刚完成依赖注入bean进行一次”初始化”
1 | protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { |
AbstractAutoProxyCreator.postProcessAfterInitialization
1 | public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { |
上面判断主要做一些检查,当所有状态合法后才会进入getAdvicesAndAdvisorsForBean
返回通过指定bean生成的通知,在通过Advisor数组生成代理对象。这个方法主要逻辑就是通过
BeanFactoryTransactionAttributeSourceAdvisor 工厂内置Advisor解析Class并且生成pointcut 切点。主要实现在AopUtils
1 | /** |
本质依然是使用BeanFactoryTransactionAttributeSourceAdvisor 内部对象来匹配Class 或Method,并且生成Advisor。
主要流程使用BeanFactoryTransactionAttributeSourceAdvisor.Pointcut(TransactionAttributeSourcePointcut 抽象类) -> TransactionAttributeSourcePointcut.matches ->AbstractFallbackTransactionAttributeSource.getTransactionAttribute
-> AnnotationTransactionAttributeSource.findTransactionAttribute ->AnnotationTransactionAttributeSource.determineTransactionAttribute -> TransactionAnnotationParser.TransactionAttribute
其中在AnnotationTransactionAttributeSource.determineTransactionAttribute 方法会使用Spring 支持TransactionAnnotationParser 数组去解析method并且返回TransactionAttribute
TransactionAnnotationParser是Spring 事务注解解析器接口在Class、Method 上解析注解并且将声明注解解析成TransactionAttribute 支持3种实现
- SpringTransactionAnnotationParser Spring自身数据库事务 解析@Transactional
- Ejb3TransactionAnnotationParser EJB事务 解析 javax.ejb.TransactionAttribute
- JtaTransactionAnnotationParser JTA1.2 事务 解析javax.transaction.Transactional
我们一起看下如何生成代理对象的createProxy
1 | protected Object createProxy(Class<?> beanClass, @Nullable String beanName, |
调用AopProxy创建代理目标类,根据不同情况初始化不同AopProxy
1 | public class DefaultAopProxyFactory implements AopProxyFactory, Serializable { |
其中JdkDynamicAopProxy 是通过InvocationHandler 接口实现,ObjenesisCglibAopProxy就是通过Cglib实现,这次只有看下Cglib如何创建动态对象的
1 | public Object getProxy(@Nullable ClassLoader classLoader) { |
Cglib样例
编写一个简单Demo类,对方法进行前后增强。
1 | public class Demo { |
编写拦截器
1 | public class CglibMethodInterceptor implements MethodInterceptor { |
最后创建代理对象
1 |
|
执行结果
invoke before….
我就是目标类原始方法
invoken after
其实跟JDK动态代理写法差不多,都是通过在原始方法前后插入代码,达到增强。CGLIB支持多个MethodInterceptor,组成一个拦截器链,按照一定顺序执行intercept。这种方法有利于AOP结构和代理业务代码解耦。
事务如何通过代理来实现的
通过上面一个小例子,我们已经了解到实现代理逻辑核心就是getCallbacks(rootClass)
返回拦截器,内置拦截器有7种,事务实现类就是在CglibAopProxy.DynamicAdvisedInterceptor。
1 | private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable { |
这个内部类主要就是两个核心方法getInterceptorsAndDynamicInterceptionAdvice,从BeanFactoryTransactionAttributeSourceAdvisor.pointcut 返回MethodInterceptor 实现类TransactionInterceptor 并且使用InterceptorAndDynamicMethodMatcher 将返回MethodInterceptor、MethodMatcher 包装起来,下面会使用到的。
将拦截器执行链作为构造器参数初始化CglibMethodInvocation,调用proceed 执行事务,proceed 会调用父类ReflectiveMethodInvocation.proceed,核心逻辑就在里面了。
1 | public Object proceed() throws Throwable { |
这里使用递归方式执行调用链
TransactionInterceptor 可以说是Spring事务执行器了,它负责执行事务,它自己本身没有任务事务实现代码,都是通TransactionManager 事务管理器来实现事务开始、回滚、提交。
直接从TransactionInterceptor.invoke 开始分析
1 | public Object invoke(MethodInvocation invocation) throws Throwable { |
invokeWithinTransaction 看方法吗方法命名就知道干什么的,执行事务方法。三个参数
Method 要执行方法,主要是获取事务注解上属性
Class 被代理Class,作业跟Method差不多
InvocationCallback 被实现的class,主要用于执行代理方法。要知道Spring AOP是代理chain 方式执行,一个类不单止是被事务代理的,还有会因为其他业务被代理了,保证代理链能全部执行下去。
1 | protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, |
总结
在这篇文章中我们简单学习了Spring初始化bean时,如何将bean创建成一个代理对象,并且使用Cglib技术创建一个代理bean,在结合事务管理器分析了代理如何去实现Spring事务的。使用一个小例子演示了Cglib代理如何实现的,方便理解Spring AOP代理是通过一个拦截器去实现的,一个对象的多个代理封装到调用链里面,执行方法时顺序执行,保证每一个代理与代理之间没有任何联系,相互独立。这次我还了解了Spring代理机制原理,通过Advisor实现类去解析Class、Method,通过PointcutAdvisor(匹配Class、Method)、IntroductionAdvisor (支持Class)是否需要生成代理对象。然后在通过专门代理工程去生成对应代理对象。
我们简单了解事务实现,其实就是环绕通知实现而已,还了解到事务状态传递是通过ThreadLocal来实现的。