We have to tell Spring two things: where to find the names, and what strategy to use (viz., autowiring by name) for autowiring.
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.
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.)
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:
SessionFactory).TransactionManager).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.
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.
Comments currently suppressed due to excessive spam. I'll reinstate them later, this time with approvals turned on. :-)