What's the difference between @Autowired and getting a bean from the application context?

13,732

By default, a Spring context will pay no attention to @Autowired annotations. In order to process them, the context needs to have a AutowiredAnnotationBeanPostProcessor bean registered in the context.

<context:annotation-config/>

registers one of these for you (along with a few others), so you do need it (unless you register AutowiredAnnotationBeanPostProcessor yourself, which is perfectly valid).

If you don't like having @Autowired in your code, then you can explicitly inject properties in the XML using , which just moves the clutter from one place to another.

If your context is extremely simple, then you can use implicit autowiring, as described here. Essentially, this tells Spring to autowire automatically by property name or type. This required very little configuration, but it very quickly gets out of control - it's automatic nature means it's hard to control, and gives you very little flexibility.

In general @Autowired really is the best option.

With application context, you are injecting the bean by yourself.

Annotation wiring isn’t turned on in the Spring container by default. So, before you can use annotation-based autowiring, you'll need to enable it in your Spring configuration. The simplest way to do that is with the

<context:annotation-config>
  <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-3.0.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config />
...
</beans>

Hope this helps.

Share:
13,732
Eric
Author by

Eric

Updated on June 13, 2022

Comments

  • Eric
    Eric almost 2 years

    I have a dao unit test that is declared as follows:

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {"classpath:spring/applicationContext.xml"})
    @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
    @Transactional
    public class RegisterDaoTest extends AbstractTransactionalJUnit4SpringContextTests {
    
        ApplicationContext applicationContext = new     FileSystemXmlApplicationContext("classpath:/spring/applicationContext.xml");
        private IRegisterDao registerDao = applicationContext.getBean(IRegisterDao.class);
    

    When I run the unit test, all pass and I can see the db getting recreated in between unit test executions.

    My test db is defined as follows:

        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
        <property name="url" value="jdbc:hsqldb:mem:test;sql.syntax_ora=true;create=true"/>
        <property name="username" value="sa"/>
        <property name="password" value=""/>
    </bean>
    
    <jdbc:initialize-database data-source="dataSource" ignore-failures="DROPS">
        <jdbc:script location="file:Artifacts/Hsql Version Scripts/install/droptables.sql" separator=";"/>
        <jdbc:script location="file:Artifacts/Hsql Version Scripts/install/install.sql" separator="/;"/>
    </jdbc:initialize-database>
    

    But when I change my test to use @Autowired, defined below, it does not execute the init db scripts.

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {"classpath:spring/applicationContext.xml"})
    @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
    @Transactional
    public class RegisterDaoTest extends AbstractTransactionalJUnit4SpringContextTests {
    
    /*
    ApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:/spring/applicationContext.xml");
        private IRegisterDao registerDao = applicationContext.getBean(IRegisterDao.class);
    */
    
        @Autowired
        private IRegisterDao registerDao;
    

    I don't see what the difference is. I have two applicationContext.xmls, one in the main and one in the test (so I can override the db with the test db)

    To me, it should execute the same. Am I missing something?

    Thanks,