2012-02-13 8 views
5

Tôi có một bài kiểm tra đơn vị dao được khai báo như sau:Sự khác biệt giữa @Autowired và nhận được một bean từ ngữ cảnh ứng dụng là gì?

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

Khi tôi chạy thử nghiệm đơn vị, tất cả các đường chuyền và tôi có thể thấy db việc tái tạo ở giữa hành đơn vị kiểm tra.

db thử nghiệm của tôi được định nghĩa như sau:

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

Nhưng khi tôi thay đổi thử nghiệm của tôi để sử dụng @Autowired, định nghĩa dưới đây, nó không thực hiện các script 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; 

Tôi không thấy sự khác biệt là gì. Tôi có hai tệp applicationContext.xml, một trong tệp chính và một trong thử nghiệm (vì vậy tôi có thể ghi đè lên db với db kiểm tra)

Với tôi, nó sẽ thực thi như vậy. Tui bỏ lỡ điều gì vậy?

Cảm ơn,

+0

IRegisterDao của bạn được xác định trong tệp xml ở đâu? bạn có thể chia sẻ điều đó không? – Nomad

Trả lời

6

Theo mặc định, một bối cảnh mùa xuân sẽ không quan tâm đến @Autowired chú thích. Để xử lý chúng, ngữ cảnh cần phải có một tên đăng ký AutowiredAnnotationBeanPostProcessor được đăng ký trong ngữ cảnh.

<context:annotation-config/> 

đăng ký một trong những cho bạn (cùng với một vài người khác), vì vậy bạn cần nó (trừ khi bạn đăng ký AutowiredAnnotationBeanPostProcessor chính mình, đó là hoàn toàn hợp lệ).

Nếu bạn không thích có @Autowired trong mã của bạn, sau đó bạn có thể tiêm một cách rõ ràng các thuộc tính trong XML bằng cách sử dụng, điều này chỉ di chuyển sự lộn xộn từ vị trí này sang vị trí khác.

Nếu ngữ cảnh của bạn cực kỳ đơn giản, thì bạn có thể sử dụng tự động ngầm, như được mô tả here. Về cơ bản, điều này cho phép Spring tự động tự động bằng tên hoặc kiểu thuộc tính. Điều này đòi hỏi cấu hình rất ít, nhưng nó rất nhanh chóng được ra khỏi tầm kiểm soát - đó là bản chất tự động có nghĩa là rất khó để kiểm soát, và cung cấp cho bạn rất ít tính linh hoạt.

Nói chung @Autowired thực sự là lựa chọn tốt nhất.

Với ngữ cảnh ứng dụng, bạn tự mình tiêm đậu.

Không được bật dây chú thích trong vùng chứa theo mặc định. Vì vậy, trước khi bạn có thể sử dụng tính năng tự động dựa trên chú thích, bạn cần phải bật tính năng này trong cấu hình Spring của mình. Cách đơn giản nhất để thực hiện điều đó là với

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

Hy vọng điều này sẽ hữu ích.

+0

Cả hai bối cảnh ứng dụng đều sử dụng cấu hình '' nhưng tôi vẫn gặp sự khác biệt. Tôi cũng đang suy nghĩ theo các dòng của bạn ... đó là lý do tại sao tôi bị nhầm lẫn là tại sao nó tạo nên sự khác biệt. – Eric

+0

@Eric, điều này có thể giúp nguyên nhân của bạn. http://hamletdarcy.blogspot.com/2008/12/autowired-junit-tests-with-spring-25.html – Nomad

0

Hai trường hợp này rất khác nhau: trong trường hợp đầu tiên bạn có HAI ngữ cảnh ứng dụng: một được tạo bởi khung kiểm thử mùa xuân và khung được tạo thủ công bởi bạn cho mỗi thử nghiệm. Khung kiểm tra Spring sử dụng @ContextConfiguration để xác định các tệp ngữ cảnh nào sẽ được tải. Nếu các thử nghiệm tiếp theo sử dụng cùng một tệp ngữ cảnh, ngữ cảnh không được tạo lại, nó sẽ được sử dụng lại.Đó là lý do tại sao db của bạn chỉ được khởi tạo một lần nếu bạn không thêm một ngữ cảnh mới theo cách thủ công.

Nếu bạn cần khởi động lại db cho mỗi bài kiểm tra, bạn nên kích hoạt nó theo cách thủ công, ví dụ như trong phương thức @Before. Bạn cũng có thể thử chú thích @DirtiesContext trong bài kiểm tra của mình, bên cạnh @ContextConfiguration.

Để làm rõ: bạn không nên tạo ngữ cảnh theo cách thủ công nếu sử dụng khung kiểm tra lò xo. @Autowired là cách tiếp cận chính xác nhưng bạn cần phải tìm các phương tiện khác để khởi tạo lại cơ sở dữ liệu của bạn trước mỗi bài kiểm tra.