【spring源码学习】spring的aop目标对象中进行自我调用,且需要实施相应的事务定义的解决方案
2017-10-12 15:22
966 查看
转载:http://www.iteye.com/topic/1122740
1、预备知识
aop概念请参考【http://www.iteye.com/topic/1122401】和【http://jinnianshilongnian.iteye.com/blog/1418596】spring的事务管理,请参考【http://jinnianshilongnian.iteye.com/blog/1441271】
使用AOP 代理后的方法调用执行流程,如图所示
@Component public class InjectBeanSelfProcessor2 implements BeanPostProcessor, ApplicationContextAware { private ApplicationContext context; //① 注入ApplicationContext public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.context = applicationContext; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if(!(bean instanceof BeanSelfAware)) { //② 如果Bean没有实现BeanSelfAware标识接口 跳过 return bean; } if(AopUtils.isAopProxy(bean)) { //③ 如果当前对象是AOP代理对象,直接注入 ((BeanSelfAware) bean).setSelf(bean); } else { //④ 如果当前对象不是AOP代理,则通过context.getBean(beanName)获取代理对象并注入 //此种方式不适合解决prototype Bean的代理对象注入 ((BeanSelfAware)bean).setSelf(context.getBean(beanName)); } return bean; } public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } }
View Code
5、总结
纵观其上:【3.1 通过ThreadLocal暴露Aop代理对象】适合解决所有场景(不管是singleton Bean还是prototype Bean)的AOP代理获取问题(即能解决目标对象的自我调用问题);
【3.2 通过初始化方法在目标对象中注入代理对象】 和【3.4 改进版的InjectBeanSelfProcessor的解决方案】能解决普通(无循环依赖)的AOP代理对象注入问题,而且也能解决【3.3】中提到的循环依赖(应该是singleton之间的循环依赖)造成的目标对象无法注入AOP代理对象问题,但该解决方案不适合解决循环依赖中包含prototype Bean的自我调用问题;
【3.3 通过BeanPostProcessor 在目标对象中注入代理对象】:只能解决 普通(无循环依赖)的 的Bean注入AOP代理,无法解决循环依赖的AOP代理对象注入问题,即无法解决目标对象的自我调用问题。
jingnianshilongnian 写道
spring允许的循环依赖(只考虑单例和原型Bean):
A----B
B----A
只有在A和B都不为原型是允许的,即如果A和B都是prototype则会报错(无法进行原型Bean的循环依赖)。
A(单例)---B(单例) 或 A(原型)---B(单例) 这是可以的,但 A(原型)---B(原型)或 A(原型)---B(单例Lazy)【且context.getBean("A")】时 这是不允许的。
一、A(原型)---B(原型) A(原型)---B(单例Lazy)【且context.getBean("A")】 会报:
Error
creating bean with name 'BServiceImpl': Injection of autowired
dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: private com.sishuok.issue.AService
com.sishuok.issue.impl.BServiceImpl.aService; nested exception is
org.springframework.beans.factory.BeanCreationException: Error creating
bean with name 'AServiceImpl': Injection of autowired dependencies
failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: private com.sishuok.issue.BService
com.sishuok.issue.impl.AServiceImpl.bService; nested exception is
org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'BServiceImpl': Requested bean is
currently in creation: [color=red]Is there an unresolvable circular
reference[/color]?
二、A(原型)---B(单例) 和 A(单例)---B(单例)
这种方式 使用我的 【3.3 通过BeanPostProcessor 在目标对象中注入代理对象】 是没有问题的。
因此【
3.4 改进版的InjectBeanSelfProcessor的解决方案 】 可以作为最后的解决方案。
相关文章推荐
- Spring Aop 目标对象内部的自我调用无法实施切面的增强处理原因
- Spring aop事务代理对象通过TransactionInterceptor处理目标方法事务过程,cglib方式
- SpringAOP功能自我调用的解决方案
- SpringBoot CGLIB AOP解决Spring事务,对象调用自己方法事务失效.
- Spring源码分析----建立AopProxy代理对象和AOP拦截器的调用
- Spring事务处理时自我调用的解决方案及一些实现方式的风险
- Spring源码学习(二)------ AOP
- SPRING.NET 1.3.2 学习21--使用对象或类的属性值进行注入
- PHP面向对象学习源码备份(二)——调用父类构造函数
- springAOP——代理对象的产生及方法调用
- Spring事务处理时自我调用的解决方案 嵌套AOP
- Spring AOP进行日志记录,管理 (使用Spring的拦截器功能获取对action中每个方法的调用情况,在方法调用前和调用后记录相关日志。)
- spring源码学习之路---AOP初探(六)
- Spring源码学习 ------ IoC——AOP
- spring aop获取目标对象的方法对象(续)
- spring源码学习之路---IOC容器初始化要义之bean定义载入(五)
- 在Spring中采用声明式方法对Hibernate和JDBC进行统一的事务配置(AOP)
- spring源码学习之路---深入AOP(终)
- spring源码学习之路---IOC容器初始化要义之bean定义载入(五)
- spring源码学习之路---深入AOP(终)