建構函式注入

將依賴項注入類的常見情況是使用建構函式注入。這涉及使用 @Inject 在類上註釋建構函式。在建立類的例項時,CDI 管理器將查詢帶有 @Inject 批註的建構函式。當它找到 @Inject-annotated 建構函式時,它將使用反射來查詢建構函式所需的引數,構造或獲取這些依賴項的例項,然後使用這些依賴項呼叫建構函式。

public class Spaceship {

    private final PropulsionSystem propulsionSystem;
    private final NavigationSystem navigationSystem;

    @Inject
    public Spaceship(PropulsionSystem propulsionSystem, NavigationSystem navigationSystem) {
        this.propulsionSystem = propulsionSystem;
        this.navigationSystem = navigationSystem;
    }

    public void launch() throws FlightUnavailableException {
        if (propulsionSystem.hasFuel()) {
            propulsionSystem.engageThrust();
        } else {
            throw new FlightUnavailableException("Launch requirements not met. Ship needs fuel.");
        }
    }

}

每當以這種方式定義的 Spaceship 例項由 CDI 建立時,它將接收 PropulsionSystem 和 NavigationSystem 作為其建構函式的引數。因為這些依賴項是通過建構函式新增的,所以我們有一種簡單的方法可以在單元測試時在測試工具中提供備用依賴項:

public class SpaceshipTest {

    private Spaceship systemUnderTest;
    private TestPropulsionSystem testPropulsionSystem;
    private TestNavigationSystem testNavigationSystem;

    @Before
    public void setup() {
        setupCollaborators();
        systemUnderTest = new Spaceship(testPropulsionSystem, testNavigationSystem);
    }

    @Test
    public void launchSequenceEngagesThrustIfFueled() {
        //given
        testPropulsionSystem.simulateHavingFuel();

        //when
        systemUnderTest.launch();

        //then
        testPropulsionSystem.ensureThrustWasEngaged();
    }

}