del.icio.us Digg DZone Reddit StumbleUpon
Annotation-Based Autowiring in Spring 2.5 - Willie Wheeler
« Previous | 1 | 2 | 3

Tell Spring about your annotation-based names and autowiring strategy

We have to tell Spring two things: where to find the names, and what strategy to use (viz., autowiring by name) for autowiring.

Tell Spring where to find the annotation-based names

You will need to use the <context:component-scan> element to do this. Since it's in the context namespace, you must declare that namespace and schema location in your Spring config files. Here are examples from the data access, service, and web configurations:

<!-- Spring configuration for data access tier -->
<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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-2.5.xsd"
    default-autowire="byName">
    
    <context:component-scan base-package="x.y.dao">
        <context:include-filter type="annotation"
            expression="org.springframework.stereotype.Repository"/>
    </context:component-scan>
    
    ...
</beans>
    
<!-- Spring configuration for service tier -->
<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"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-2.5.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
    default-autowire="byName">
    
    <context:component-scan base-package="x.y.service">
        <context:include-filter type="annotation"
            expression="org.springframework.stereotype.Service"/>
    </context:component-scan>

    ...
</beans>
    
<!-- Spring configuration for web tier -->
<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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-2.5.xsd"
    default-autowire="byName">
    
    <context:component-scan base-package="x.y.web">
        <context:include-filter type="annotation"
            expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    ...
</beans>

(You'll of course need to provide the proper value for the base package.)

In the above, the pieces relevant to component names are the xmlns:context declaration, the xsi:schemaLocation declaration, and the <context:component-scan> configuration. I'm telling Spring to scan the x.y.dao package for components that have the @Repository annotation, to scan the x.y.service package for components that have the @Service annotation, and to scan x.y.web for components that have the @Controller annotation. Spring will do that, and in the case of the data access and service components, it will use the value we provided to the annotations in step 1 above as a basis for name-based autowiring. (We didn't provide any names with the @Controller annotation though I would assume you can do that. It happens that in our case we won't need it.)

You'll notice however that I've snuck in some default-autowire="byName" attributes in there. As you can guess, that's for autowiring, and we'll look at that in just a second.

Make sure you have public setters for each bean that you want autowired.

It appears that default-autowire="byName" autowiring is based on public setters. (With the @Autowired attribute applied to fields you can avoid the setters, but if you have unit tests, you'll need setters to inject mocks, and so you may as well just keep the setters and make them public. Weaker visibility doesn't appear to work.)

Tell Spring that you want to use name-based autowiring

The default-autowire="byName" attribute tells Spring that you want to use component names to automatically wire up the app. In step 1 above we went through the process of providing correct names ("correct" here means names that match the injection property names) for DAO and service classes. That will allow us to remove the DAO and service components from our Spring config. In all likelihood there will be other components that you can't remove from the config, such as a Hibernate SessionFactory in your data access configuration or a TransactionManager in your services configuration. In cases like that, just make sure that the names (or IDs) that you give to the components are the ones that would be expected when doing name-based injection. Here are some examples:

<!-- Hibernate session factory -->
<bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    ...
</bean>
 
<!-- Hibernate transaction manager -->
<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

Note that using default-autowire="byName" allows you to avoid having to use the @Autowired attribute on your various dependency injection fields or setters. You shouldn't have to use that at all if you follow these instructions.

At this point you should be able to remove the following configurations:

  • The DAO component definitions from your Spring data access configuration file (but don't remove the SessionFactory).
  • The service component definitions from your Spring service configuration file (but don't remove the TransactionManager).
  • The service injections from your MVC controllers in your web configuration file. Don't remove the controllers themselves for now; you still need those for defining URL mappings. Just remove the service injections since those will now be autowired. (Note that there's a way to eliminate the MVC controller configurations as well; see Annotation-Based MVC in Spring 2.5 for details.)
  • The sessionFactory injection from your TransactionManager definition since that will be autowired, the dataSource injection from your SessionFactory (assuming you have an appropriate ID on the DataSource config), etc. In general just look through your configs for elements that will now be autowired and either comment them out or remove them.

I would recommend commenting things out first and then testing the app to make sure it still works.

Congratulations!

Your app should now be autowired. As mentioned above, if you want to go the full distance and remove the controller configs, please see my article Annotation-Based MVC in Spring 2.5.

Interested in learning about Acegi security for Spring? Please see my five-minute Acegi Overview.

Social bookmarks: del.icio.us Digg DZone Reddit StumbleUpon
« Previous | 1 | 2 | 3

Comments (22)

I enjoyed your article very much and I think this is very usefull information. I have a great fan of spring framework project and I use it wiht Struts 2 Web framework.

May question is.... would this @Controller annotations work in other Java web frameworks such as Struts 2?

Kind regards,

Flavio Oliva
By flavio Oliva on Mar 10, 2008 at 12:13 PM PDT
Hi Flavio. Thanks for your kind comments regarding the article. I'm also a big fan of Spring. :-) Regarding @Controller, that is a Spring-specific annotation. I haven't checked out Struts 2 yet so I don't know whether Struts 2 has a corresponding annotation, but I wouldn't expect Spring's @Controller annotation to work there.
By Willie Wheeler on Mar 10, 2008 at 7:59 PM PDT
Willie,

Nice article. I just wanted to point out that the "include-filter" in your component-scan element is not actually required since all of Spring's stereotype annotations (including: org.springframework.stereotype.Controller) are automatically included.

-Mark
By Mark Fisher on Mar 18, 2008 at 9:31 AM PDT
Hi Mark. Thanks for the comments. You are right about the <include-filter> part. In the app on which this code is based, I have the data, service and servlet configs separated out into different application context files, and I use the <include-filter> to avoid rescanning the same components over and over. But you are right that one could omit it and have a cleaner config. So take your pick. :-)
By Willie Wheeler on Mar 18, 2008 at 10:33 PM PDT
Hi Willie,

Say if I have this:

<bean id="hibernateDao" abstract="true">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>


<bean id="testDao" class="com.some.TestDaoImpl" parent="hibernateDao" />

public class TestDaoImpl extends HibernateDaoSupport implements TestDao {...

How do I convert my testDao to use annotation? I am clear on how to take care of the parent param.

Do you know if there are any spring configuration xml to annotation cheat sheets around? There are many more complex configurations in xml I don't see how to convert into annotations.

Thanks,

Derek
By Derek Lin on Jun 11, 2008 at 4:04 PM PDT
oops. I meant NOT clear:

Hi Willie,

Say if I have this:

<bean id="hibernateDao" abstract="true">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>


<bean id="testDao" class="com.some.TestDaoImpl" parent="hibernateDao" />

public class TestDaoImpl extends HibernateDaoSupport implements TestDao {...

How do I convert my testDao to use annotation? I am NOT clear on how to take care of the parent param.

Do you know if there are any spring configuration xml to annotation cheat sheets around? There are many more complex configurations in xml I don't see how to convert into annotations.

Thanks,

Derek
By Derek Lin on Jun 11, 2008 at 4:06 PM PDT
Hi Derek. I doubt there's a way to do that though I can't say with 100% certainty. If it's any consolation, though, you can autowire the session factory into the TestDao. I know that's not quite the same thing but it does reduce explicit XML configuration.
By Willie Wheeler on Jun 13, 2008 at 1:45 AM PDT
Magic! This has made my xml files so small I can hardly see them.

Thanks for another brilliantly written article, Willie.
By Paul Schwarz on Jun 17, 2008 at 8:39 AM PDT
Hi
Default spring will support autowire="no" and i read manning struts2 book struts2 it supprots default autowire to "byName" when it integrates with spring. Then which one it will consider. Either byName or no.
By Ramesh Alla on Aug 6, 2008 at 4:40 AM PDT
Hi Ramesh. Like I mentioned to Flavio above, I haven't used Struts 2 so I can't myself speak to that. (I understand from others though that Struts 2 is pretty good.) Maybe somebody else can answer this one?
By Willie Wheeler on Aug 6, 2008 at 8:03 PM PDT
Exellent
By Nick on Sep 4, 2008 at 8:01 PM PDT
I've found auto-wiring to be generally problematic and it often creates "interesting" bugs.

One of the things I love about Spring is the way it supports interface driven design. The major issue with auto-wiring is, it works best when there is only one implementation of an interface (an area where critics ask why bother using interfaces).

I often have multiple implementations of a given interface so, when auto-wiring does work (without throwing start-up exceptions) it often plugs in the wrong implementation.

OTOH, I've found auto-wiring works beautifully in tests. These are cases where small specific Spring config files are used. The simplicity offered by auto-wiring in unit tests is a wonderful thing.

Keep up the good work with the posts
By Paul on Oct 28, 2008 at 4:03 PM PDT
The article generally are nice on your website and this one is no exception, however i have one question related to transaction management, could that also be configured through annotations somehow?
By Vaibhav on Nov 19, 2008 at 3:55 PM PST
Hi Vaibhav. Yep. See

http://wheelersoftware.com/articles/spring-transactions-annotations.html
By Willie Wheeler on Nov 19, 2008 at 3:58 PM PST
Thanks sir!!! you rock!!
By Vaibhav on Nov 19, 2008 at 6:44 PM PST
I try. ;-)
By Willie Wheeler on Nov 19, 2008 at 7:47 PM PST

Very nice tutorial.

By Eswar on Jun 29, 2009 at 3:57 PM PDT

Newbie question :

Lets say my interface is CarService, and I've two implementing classes viz. FerrariService and HondaService with @Service("carService")

In my controller class I've a reference CarService carService. How will Spring determine which implementing class (Ferrari/Honda) am I looking for?

Do I have to change annotation in Service classes to @Service("ferrariService") and @Service("hondaService") respectively and in my controller use CarService ferrariService and CarService hondaService?

By AnnotationNewbie on Jul 1, 2009 at 7:05 AM PDT

Ok, I think I this post - http://sleeplessinslc.blogspot.com/2008/02/introduction-software-development-and.html explains it.

By AnnotationNewbie on Jul 10, 2009 at 10:12 AM PDT

really very nice tutorial. I like this . The steps followed by you is really great.

Thanks a lot.

Regards, Sunil

By sunil kumar on Sep 29, 2009 at 11:14 PM PDT

Hi:

Really noice tutorial!! Is there a link to download the source code to try out?

Yours,

John

By John Smith on Dec 30, 2009 at 11:54 PM PST
  1. Ok, thanks for the answer. We're not yet using 2.5 anyway, so it's more an out-of-interest question than a practical one. But if we moved to 2.5 and abandoned most of our existing XML wiring, I'd certainly want to try to get rid of the equivalent in faces-config as well. And as I said, it shouldn't be too hard to solve in-house with some kind of post-processor, right?

By web development on Mar 7, 2010 at 5:01 PM PST

Post a comment

Your name:
Your e-mail address (won't be displayed):
Your web site (optional):
example: www.xyz.com
Your comment:
Preview:
By You
Please help us reduce comment spam:
Spring Annotations RefCard
Check out the new DZone Spring Annotations Refcard by Craig Walls!

What's New?

2009-08-30 - Check out my two-part series on DZone: Spring Integration: A Hands-On Tutorial.
2009-03-25 - My new article Getting Started with Spring Batch 2.0 is available on DZone.
Home | Consulting | Tech Articles | Mailing List | Contact | Spring Blog
Copyright © 2008 Wheeler Software, LLC.