控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦度其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递(注入)给它。
Dependency Injection,依赖注入的基本思想是:不需要自己创建对象实例,由他人或容器创建并注入到对应的变量中,直接拿来使用。通过使用Spring框架,容器中的实例(Bean)可以被注入到被@Autowired注解的变量中,从而实现依赖注入。
容器查找Bean再注入相应变量的过程:
- 根据变量类型到容器中查找Bean。
- 如果容器中有多个相同类型的Bean再根据变量的名称作为Bean的ID去查询。
- 所以当容器中有多个类型相同的Bean时,容器先会使用变量的名称作为查找的Bean ID去查找并注入到变量中。
- 更为谨慎的方式是对变量使用@Qualifier注解,value为Bean ID,容器会查找对应的Bean并注入到变量中去。
- 当不使用@Qualifie时,还可以使用@Primary指定注入到变量的首选Bean。
- 当同时使用@Qualifier和@Primary时,@Qualifier优先级更高。
- @Autowired还可以设置required参数;当值为false时,不要求一定要在容器中找到对应的Bean并注入。
这里我们来演示使用@Autowired的过程。
- 在配置类中把Bean注入(添加)容器中
import com.michael.annotation.demo.POJO.Student;
import org.springframework.context.annotation.*;@Configuration
public class MyConfig {
@Primary@Scope("singleton")@Bean(value = "s1")public Student student1(){
Student s1 = new Student();s1.setName("s1");return s1;}@Scope("singleton")@Bean(value = "s2")public Student student2(){
Student s2 = new Student();s2.setName("s2");return s2;}
}
这里名为"s1"的Bean被设置为首选Bean。
- 创建服务类并且通过@Service注解添加到容器中
import com.michael.annotation.demo.POJO.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;@Service
public class StudentService {
@Qualifier("s2")@Autowired(required = false)private Student student2;@Autowiredprivate Student student1;public void showInfo(){
System.out.println(student1);System.out.println(student2);}
}
这里student2指名要注入ID为"s2"的Bean,student1会被注入ID为"s1"的Bean。
- 测试代码:
import com.michael.annotation.demo.service.StudentService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;import static java.lang.System.out;@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ApplicationContext applicationContext = SpringApplication.run(DemoApplication.class, args);out.println("The container has been initialized.");((StudentService)applicationContext.getBean("studentService")).showInfo();out.println("The container has been destroyed.");}
}
- 输出:
The container has been initialized.
Student{
name='s1', ID='null', age=null}
Student{
name='s2', ID='null', age=null}
The container has been destroyed.
- 观察输出,可以发现:@Qualifer的优先级大于@Primary。
https://zh.wikipedia.org/wiki/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC