Prasanna
Prasanna

Reputation: 2488

Spring Web - Circular Reference on enabling AspectJ & Transaction Management

Spring Web results in circular reference under the following condition

  1. Enable AspectJ AutoProxy & Transaction Management
  2. Create a simple bean, B1 expected to be loaded first
  3. Create a ProxyFactoryBean, B2 that depends on B1

Below is my analysis.

  1. Spring tries to create Bean B1. At this point, AnnotationAwareAspectJAutoProxyCreator BPP kicks in.
  2. The AutoProxyCreator intends to create TransactionAdvicer & tries to find all beans of TransactionManagementConfigurer type
  3. B2 being a Factory bean (The shortcut to check factory bean type failed as well), spring needs to create complete bean B2 to compare the type. As B2 is dependent on B1, it results in a circular reference.

One workaround was to ensure that Spring first loads a dummy bean say B0, that no bean will depend on.

Java Configuration:

@Configuration
@DependsOn("testBean2")
@EnableTransactionManagement
public class TestConfig
{
   @Bean
   public PlatformTransactionManager transactionManager()
   {
      DriverManagerDataSource dataSource = new DriverManagerDataSource();
      // MySQL database we are using
      dataSource.setDriverClassName("com.mysql.jdbc.Driver");
      dataSource.setUrl("jdbc:mysql://localhost:3306/db");// change url
      dataSource.setUsername("username");// change userid
      dataSource.setPassword("password");// change pwd

      PlatformTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);
      return transactionManager;
   }
}

XML Configuration:

<?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>

Upvotes: 0

Views: 312

Answers (1)

Mạnh Quyết Nguyễn
Mạnh Quyết Nguyễn

Reputation: 18235

Move your @Bean declaration to a @Configuration class.

It will prevent one bean method called twice

Upvotes: 0

Related Questions