Spring v3.0.2 Learning Note 7 - Constructor-based dependency injection

基於構造器的注入方式

package com.spring.test.dao;

public class PersonDao {

    public void add() {
        System.out.println("This is add() method in DAO layer.");
    }
}
--------------------------------------------------------------------------
package com.spring.test.manager.impl;

import com.spring.test.dao.PersonDao;
import com.spring.test.manager.IPersonService;

public class PersonManager implements IPersonService {

    private PersonDao personDao;
    private String name;

    public PersonManager() {
    }

    public PersonManager(PersonDao personDao, String name) {
        super();
        this.personDao = personDao;
        this.name = name;
    }

    @Override
    public void save() {
        personDao.add();
        System.out.println("name is " + name);
    }

}

該類的構造函數有2個屬性,一個是類PersonDao,一個是String類型的變量。spring關於構造器注入的配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="personDao" class="com.spring.test.dao.PersonDao" />
    <bean id="personService" class="com.spring.test.manager.impl.PersonManager">
        <constructor-arg index="0" type="com.spring.test.dao.PersonDao"
            ref="personDao" />
        <constructor-arg index="1" type="java.lang.String"
            value="name string" />
    </bean>
</beans>
這是關於constructor-arg的設置,其作用就是通過構造器注入依賴的對象或基本數據類型的值。
 index從0開始計數,其順序要與類中的參數一一對應。

測試類:
package com.spring.test.junit;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.spring.test.manager.IPersonService;

public class PersonServiceTest {

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {
    }

    @Test
    public void test() {
        AbstractApplicationContext ctx = new ClassPathXmlApplicationContext(
                "spring.xml");
        IPersonService personService = (IPersonService) ctx
                .getBean("personService");
        personService.save();
    }

}
運行該測試類,可看到正確的注入結果。

基於構造器的注入還是基於Setter方式的注入?
推薦採用Setter的注入方式,以下內容來自spring的參考文檔

Constructor-based or setter-based DI?

Since you can mix both, Constructor- and Setter-based DI, it is a good rule of thumb to use constructor arguments for mandatory dependencies and setters for optional dependencies. Note that the use of a @Required annotation on a setter can be used to make setters required dependencies.
The Spring team generally advocates setter injection , because large numbers of constructor arguments can get unwieldy, especially when properties are optional. Setter methods also make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is a compelling use case.
Some purists favor constructor-based injection. Supplying all object dependencies means that the object is always returned to client (calling) code in a totally initialized state. The disadvantage is that the object becomes less amenable to reconfiguration and re-injection.
Use the DI that makes the most sense for a particular class. Sometimes, when dealing with third-party classes to which you do not have the source, the choice is made for you. A legacy class may not expose any setter methods, and so constructor injection is the only available DI.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章