Spring中@Autowired 注解的注入規則


默認根據類型,匹配不到則根據bean名字

 

1.聲明一個service接口

public interface HelloService {
    void sayHello();
}

 

2.service接口的實現類,此時bean名字是 helloServiceImpl

@Service
public class HelloServiceImpl implements HelloService {
    @Override
    public void sayHello() {
        System.out.println("say hello impl");
    }
}

 

3.增加一個Controller,注入service

// 生成一個bean,名字為 helloController
@Controller
public class HelloController {
    @Autowired
    private HelloService helloService;
    
    public void hello() {
        helloService.sayHello();
    }
}

 

4.測試①:

public class AppTest {
    
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        HelloController controller = (HelloController) context.getBean("helloController");
        controller.hello();
    }
}

 

結果如下

成功將Service層的實現類注入到Controller層中,可以把步驟3 代碼修改一下

// 生成一個bean,名字為 helloController
@Controller
public class HelloController {
    @Autowired
    private HelloService abc;
    
    public void hello() {
        abc.sayHello();
    }
}

結果也是可以的,因為@Autowired 第一是按照類型去匹配的,此時IoC容器中HelloService 接口只有一個實現類,所以屬性名字怎么寫都沒關系,都可以注入進去

 

測試②:增加一個實現類,此時bean名字是 newServiceImpl

@Service
public class NewHelloServiceImpl implements HelloService {
    @Override
    public void sayHello() {
        System.out.println("new say hello impl");
    }
}

 

現在IoC容器中有兩個 HelloService接口的實現類,繼續運行測試方法,結果為

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'helloController':
Unsatisfied dependency expressed through field 'abc';
nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type 'com.convict.service.HelloService' available:
expected single matching bean but found 2: helloServiceImpl,newHelloServiceImpl

 

因為一個接口有多個實現,所以@Autowired 就按照屬性名字去找,即找一個名字為 abc的bean注入,然而IoC容器不存在一個名字叫abc的 bean,因此報錯,把屬性名改為下面任意一種就可以匹配到了

// 生成一個bean,名字為 helloController
@Controller
public class HelloController {
    @Autowired
    private HelloService helloServiceImpl;
    
    @Autowired
    private HelloService newHelloServiceImpl;
    
    public void hello() {
        helloServiceImpl.sayHello();
        newHelloServiceImpl.sayHello();
    }
}

 

測試③:

那我就要把屬性名叫 abc,同時有多個實現,而且還能注入,那么在聲明組件的時候取個名字就好了,比如

@Service("abc")
public class HelloServiceImpl implements HelloService {
    @Override
    public void sayHello() {
        System.out.println("say hello impl");
    }
}

 

然后Controller 注入的還是abc,結果注入成功

// 生成一個bean,名字為 helloController
@Controller
public class HelloController {
    @Autowired
    private HelloService abc;
    
    public void hello() {
        abc.sayHello();
    }
}

 

測試④:

屬性名叫 abc,同時有多個實現,同時可以注入,且不在注解處聲明bean 的名字,那么這時候使用新的注解@Qualifier 配合@Autowired 一起使用

// 生成一個bean,名字為 helloController
@Controller
public class HelloController {
    @Autowired
    @Qualifier("helloServiceImpl")
    private HelloService abc;
    
    public void hello() {
        abc.sayHello();
    }
}

@Qualifier是指定 一個bean的名字

 

總結:

1.一個接口只有一個實現的情況下,屬性名字怎么寫都無所謂,因為按照類型匹配就只有一個bean

2.一個接口多個實現的情況下:

  ① 屬性名字跟組件名字一致,組件名字可以在聲明的時候指定,比如 @Service("abc")

   ② 屬性名字跟組件名字不一致,配合@Qualifier 注解指定組件名字

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM