@Qualifier not working after upgrade from Spring3 to Spring4

We have struts 1.x used with Spring 3.x in our project. In the process of upgrading from spring 3->4, our qualifier annotation in the struts action does not work any more. After digging in and compare the Spring 3 and 4, finally found the reason.

1.QualifierAnnotationAutowireCandidateResolver is not the default resolver in spring 4

In Spring 3, after we create our beanfacotry in the application context, Spring will explicitly call :

beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());

In spring 4, it is not called any more in the AbstractRefreshableApplicationContext’s protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory).

So for the parent(root) context, it should still work as is if you have the <context:annotation-config/> in the config xml. However for the child context the default resolver will become ‘SimpleAutowireCandidateResolver’

2.The child resolver is passed to parent when trying to determine ‘isAutowireCandidate()’ in Spring 4’s DefaultListableBeanFactory

The isAutowireCandidate() will delegate the responsibility to parent beanFactory if it cannot make decision.

In Spring 3, the delegation does not pass the resolver to the parent so that parent context uses its own resolver to call the isAutowireCandidate(). However in Spring 4, it changes. The resolver is passed as a parameter to the parent who uses it to call the isAutowireCandidate(). So even the parent has a ContextAnnotationAutowireCandidateResolver which extends QualifierAnnotationAutowireCandidateResolver as its resolver, it still does not help.

Spring 3.1.2 DefaultListableBeanFactory source code

Spring 4.1.6  DefaultListableBeanFactory source code 

Solution

The simple solution to me is to set the resolver to QualifierAnnotationAutowireCandidateResolver using a BeanFactoryPostProcessor. The good thing is Spring already provided one for us.

org.springframework.beans.factory.annotationCustomAutowireConfigurer

So the config should be added to the CHILD context config xml

    <bean id="customAutowireConfigurer" class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
        <property name="customQualifierTypes">
            <set>
                <value>org.springframework.beans.factory.annotation.Qualifier</value>
            </set>
        </property>
    </bean>

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s