網頁

2019/12/6

Spring @Autowired 搭配 @Qualifier 指定注入的Bean

Spring 使用@Autowired注入的介面有多個@Bean類時,可以搭配@Qualifier控制要注入哪個實例。


例如下面是DemoService介面,目前有兩個實作Bean類分別為DemoServiceOneImplDemoServiceTwoImpl

DemoService

package com.abc.demo.servce;

public interface DemoService {
    public void doService();
}

@Service注釋宣告這個Bean的名稱,例如DemoServiceOneImpl的Bean名稱為"one"

DemoServiceOneImpl

package com.abc.demo.servce;

import org.springframework.stereotype.Service;

@Service("one") // <-- bean name is "one"
public class DemoServiceOneImpl implements DemoService {
    @Override
    public void doService() {
        System.out.println("This is one...");
    }
}

DemoServiceTwoImpl的Bean名稱為"two"

DemoServiceTwoImpl

package com.abc.demo.servce;

import org.springframework.stereotype.Service;

@Service("two") // <-- bean name is "two"
public class DemoServiceTwoImpl implements DemoService {
    @Override
    public void doService() {
        System.out.println("This is two...");
    }
}

下面為使用@Autowired注入DemoService實例的DemoController。由於DemoService有兩個Bean,所以此時可加上@Qualifier來決定要注入哪個Bean實例,例如下面注入的實例為DemoServiceOneImpl

package com.abc.demo.controller;

import com.abc.demo.servce.DemoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoController {

    @Qualifier("one") // <-- 告訴Spring注入名稱為"one"的Bean,即DemoServiceOneImpl
    @Autowired
    private DemoService demoService;

    @GetMapping("/")
    public void demo() {
        demoService.doService(); // 多型,所以實際上是呼叫DemoServiceOneImpl.doService()
    }

}

若有多個Bean但沒用@Qualifier指明注入的對象,例如把上面@Qualifier移除,則Spring啟動時會出現下面錯誤。

***************************
APPLICATION FAILED TO START
***************************

Description:

Field demoService in com.abc.demo.controller.DemoController required a single bean, but 2 were found:
 - one: defined in file [../workspace/demo/target/classes/com/abc/demo/servce/DemoServiceOneImpl.class]
 - two: defined in file [../workspace/demo/target/classes/com/abc/demo/servce/DemoServiceTwoImpl.class]


Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed


Process finished with exit code 1


沒有留言:

張貼留言