Feb 9th, 2010, 03:13 AM
disable circular references by default
I would like to share my experience and ask your opinion regarding circular references, which are enabled by default (see javadoc). The problem can occur when xml and annotation based configuration is used together. The problem is not visible immediately, it is hard to find and it can cause unpredictable behavior in the application.
I have experienced the following problem:
- I have two proxied bean PA and PB (proxied using the ProxyFactoryBean and configured in XML). They have transaction interceptor configured through the interceptorNames property. PA's target is inner bean A, PB's target is inner bean B.
- They are defined in the application context xml file in the order PA, PB.
- I have a bean C provided through the @Component annotation to the application context
- A has a dependency to C configured through the @Autowired annotation
- B has a dependency to PA (configured in xml)
Proxy bean PA will be created without the transaction interceptor despite the fact, that the interceptor is configured in the bean definition.
Reason of the problem:
When the A -> C dependency is resolved by the bean factory (it is resolved by type), proxy bean PB and its target B is created (it is created because its type must be evaluated). When B is created, PA is only partly initialized and PA's interceptorNames property is not set yet! Unfortunately in this point the ProxyFactoryBean's initializeAdvisorChain() method is called and the configured advisors for PA will be not created at all, as interceptorNames property is not set yet! This initialization is done just once (initialization call is remembered through a boolean flag in ProxyFacoryBean), so PA will be used without any advisor in the application.
Possible solutions to solve this problem:
- Set the mentioned allowCircularReferences to false in your application context
- Put the bean's definition to the xml file in the following order: PB, PA - bean creation is done according to the order of bean definitions in the xml and in this case PB will be created before the A -> C dependency is resolved.
- Do not mix xml configuration and configuration through @Autowired annotation for proxied beans which are dependent
Topic for discussion:
The enabling of circular references is not recommended according to the javadocs. Despite of this recommendation its value is true by default (it is enabled by default). Setting value to false can be done only through the java api, when the application context is created. The creating of application context is often done in Spring's components (in Spring MVC for example), so it is not created in an application code and it is not possible to set the value to false before the xml configuration file(s) are provided for the application context object. In such cases the application context must be refreshed after setting allowCircularDependencies to false. Such refresh can be time consuming.
Will not be better to have false value for allowCircularDependencies by default? What do You think?