This article describe a situation that could lead to unexpected Spring’s behaviour, in terms of instantiated beans, caused by multiple dependent context files.
I do not like this approach, but I have to cope with it and mostly fix the problems (analyzing the Spring’s initialization logs).

Tested with Spring 3; this examples talks about context files, but it could apply to Java Config scenarios as well.

Let’s imagine we have various interdipendent modules (first.jar, second.jar, …), everyone with its own context file:

  • first-context.xml
  • second-context.xml
  • third-context.xml
  • fourth-context.xml

Both second and third contexts import the first and are imported by the fourth.
More over the first and the second context define the same bean (i.e. two beans with the same id).

In first-context.xml:


<bean id="myBean" class="it.caladyon.RustedImplementation">...

In second-context.xml:


<bean id="myBean" class="it.caladyon.ShinyImplementation">...

Now the question is: “Which implementation has Spring instantiated?”

The answer is: it depends on the fourth context’s import order, because the last definition wins.
Let’s explain with two examples.

Example A: fourth-context.xml imports second-context.xml before third-context.xml.

In this case, myBean is a RustedImplementation instance, because:

  1. Spring reads myBean definition from first-context.xml (imported by second-context.xml)
  2. Spring reads myBean definition from second-context.xml
  3. Spring reads myBean definition from first-context.xml (imported by third-context.xml)

Example B: fourth-context.xml imports third-context.xml before second-context.xml.

In this case, myBean is a ShinyImplementation instance, because:

  1. Spring reads myBean definition from first-context.xml (imported by third-context.xml)
  2. Spring reads myBean definition from first-context.xml (imported by second-context.xml)
  3. Spring reads myBean definition from second-context.xml

How to debug

To debug this kind of situation, you could log Sping’s activity at INFO level and look for this kind of messages:

INFO [DefaultListableBeanFactory:623] Overriding bean definition for bean 'myBean': 
replacing [Generic bean: class [it.caladyon.ShinyImplementation];... defined in class path resource [second-context.xml]] 
with [Generic bean: class [it.caladyon.RustedImplementation];... defined in class path resource [first-context.xml]]

 

Annunci