В чем разница между @Autowired и получением компонента из контекста приложения? - PullRequest
6 голосов
/ 13 февраля 2012

У меня есть модульный тест dao, который объявляется следующим образом:

@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);

Когда я запускаю модульный тест, все проходят, и я вижу воссоздание БД между выполнением модульного теста.

Моя тестовая база данных определяется следующим образом:

    <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>

Но когда я изменяю свой тест на использование @Autowired, определенного ниже, он не выполняет сценарии init db.

@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;

Я не вижу, в чем разница.У меня есть два applicationContext.xmls, один в основном и один в тесте (поэтому я могу переопределить БД с помощью теста БД)

Для меня это должно выполняться одинаково.Я что-то упустил?

Спасибо,

Ответы [ 2 ]

7 голосов
/ 13 февраля 2012

По умолчанию контекст Spring не будет обращать внимания на аннотации @ Autowired . Для их обработки в контексте должен быть зарегистрирован компонент AutowiredAnnotationBeanPostProcessor .

<context:annotation-config/>

регистрирует один из них для вас (вместе с несколькими другими), поэтому он вам нужен (если только вы не зарегистрируете AutowiredAnnotationBeanPostProcessor , что совершенно правильно).

Если вам не нравится, когда в вашем коде есть @ Autowired , вы можете явно внедрить свойства в XML-код, используя который просто перемещает беспорядок из одного места в другое.

Если ваш контекст очень прост, тогда вы можете использовать неявную автопроводку, как описано здесь . По сути, это говорит Spring, чтобы автоматически подключаться по имени или типу свойства. Для этого потребовалось очень мало настроек, но он очень быстро вышел из-под контроля - его автоматическая природа означает, что им трудно управлять, и дает вам очень мало гибкости.

В общем @ Autowired действительно лучший вариант.

В контексте приложения вы вводите компонент самостоятельно.

По умолчанию проводка аннотации в контейнере Spring не включена. Итак, перед вами Вы можете использовать автоматическое подключение на основе аннотаций, вам нужно включить его в конфигурации Spring. Самый простой способ сделать это с помощью

<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>

Надеюсь, это поможет.

0 голосов
/ 13 февраля 2012

Эти два сценария очень разные: в первом случае у вас есть ДВА контекста приложения: один, созданный в рамках среды тестовой пружины, и один, созданный вами вручную для каждого теста.Среда тестирования Spring использует @ContextConfiguration, чтобы определить, какие файлы контекста должны быть загружены.Если последующие тесты используют одни и те же файлы контекста, контекст не воссоздается, он используется повторно.Вот почему ваша база данных инициализируется только один раз, если вы не создаете новый контекст вручную.

Если вам нужно повторно инициализировать БД для каждого теста, вы должны запустить его вручную, например, в методе @Before.Вы также можете попробовать аннотацию @DirtiesContext в своем тесте, рядом с @ContextConfiguration.

Чтобы прояснить: вам не следует создавать контекст вручную, если вы используете среду весеннего тестирования.@Autowired - правильный подход, но вам нужно найти другие средства для повторной инициализации базы данных перед каждым тестом.

...