启用AspectJ与事务管理时Spring Web循环依赖问题分析与解决
Spring Web循环引用的触发场景、根源分析与解决方案
我之前在项目里碰到过一模一样的Spring循环引用问题,刚好对应你描述的场景,下面给你详细拆解:
触发循环引用的三个必要条件
- 同时启用AspectJ AutoProxy和事务管理
- 定义一个预期会被优先加载的简单Bean(比如示例中的B1)
- 创建依赖上述简单Bean的
ProxyFactoryBean类型Bean(比如示例中的B2)
问题的深层原因
Spring容器初始化时的执行链路导致了这个死循环:
- Spring开始实例化Bean B1,此时
AnnotationAwareAspectJAutoProxyCreator后置处理器启动工作 - 这个AutoProxyCreator需要创建
TransactionAdvicer,而创建它的过程中会去查找所有TransactionManagementConfigurer类型的Bean - 由于B2是Factory Bean,而且Spring的Factory Bean快捷类型检查机制失效了,Spring必须完整实例化B2才能判断它的类型,但B2本身依赖B1,这就形成了B1→TransactionAdvicer→B2→B1的循环依赖链
快速解决办法
一个简单且有效的方案是:让Spring优先加载一个完全不依赖其他Bean的虚拟Bean(比如示例中的testBean2),通过调整初始化顺序来打破这个循环。
Java配置示例
@Configuration @DependsOn("testBean2") @EnableTransactionManagement public class TestConfig { @Bean public PlatformTransactionManager transactionManager() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/db");// 根据你的数据库环境修改 dataSource.setUsername("username");// 替换为实际用户名 dataSource.setPassword("password");// 替换为实际密码 PlatformTransactionManager transactionManager = new DataSourceTransactionManager(dataSource); return transactionManager; } }
XML配置示例
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <aop:aspectj-autoproxy /> <context:component-scan base-package="test.config" /> <bean id="testBean2" class="test.beans.TestBean2" /> <bean id="testTransactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager" ref="transactionManager" /> <property name="transactionAttributes"> <props> <prop key="audit">PROPAGATION_REQUIRES_NEW</prop> </props> </property> </bean> <bean id="testBean1" class="org.springframework.aop.framework.ProxyFactoryBean" depends-on="testBean2"> <property name="target"> <bean class="test.beans.TestBean1" /> </property> <property name="interceptorNames"> <list> <value>testTransactionInterceptor</value> </list> </property> </bean> </beans>
内容的提问来源于stack exchange,提问作者Prasanna
相关产品推荐
相关产品推荐

