共计 4278 个字符,预计需要花费 11 分钟才能阅读完成。
所谓 spring 主动注入,是指容器中的一个组件中须要用到另一个组件(例如聚合关系)时,依附 spring 容器创建对象,而不是手动创立,次要有三种形式:
- @Autowired 注解——由 spring 提供
- @Resource 注解——由 JSR-250 提供
- @Inject 注解——由 JSR-330 提供
@Autowired 注解的应用办法
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
/**
* Declares whether the annotated dependency is required.
* <p>Defaults to {@code true}.
*/
boolean required() default true;}
从源码能够看出:该注解能够用在结构器、办法、参数、属性上,最常见的是用在属性上。
该注解只有一个属性:required,默认为 true,如果找不到匹配的 bean 则报错;设置为 false,如果找不到匹配的 bean 则注入 null,并不会报错。
能够配合 @Qualifier 应用,用于精准指定要注入的 bean 的名称。
能够配合 @Primary 应用,当容器中存在多个雷同类型的组件时,用于指定优先加载哪一个,这个注解不能用在 2 个或更多同类型的组件上。
- 当容器中只有一个该类型的组件时
|- 不应用 @Qualifier,会按 bean 类型查找,即 applicationContext.getBean(bean.class),而后注入这个惟一的 bean。
|- 应用 @Qualifier,会按 Qualifier 的 value 值跟 bean 名称匹配查找,即 applicationContext.getBean(“Qualifier 的 value 值 ”)。 - 当容器中没有该类型的组件时
|-required=true——报错 expected at least 1 bean which qualifies as autowire candidate。
|-required=false——注入 null。 - 当容器中存在多个该类型的组件时
|- 不应用 @Qualifier 和 @Primary 时,会按属性名跟 bean 名称匹配查找,即 applicationContext.getBean(“ 属性名 ”)。
|- 应用 @Primary、但不应用 @Qualifier 时,会优先加载带有 @Primary 注解的组件。
|- 应用 @Qualifier 时,不论有没有应用 @Primary,都会间接按 Qualifier 的 value 值跟 bean 名称匹配查找。
综上,当容器中存在多个同类型的组件时,加载优先级:@Qulifier>@Primary> 属性名,例如上面这个容器中蕴含 3 个 BookDao 组件
@Configuration
@ComponentScan(basePackages = {"cn.monolog.service"})
public class AutowiredBeanConfig {@Bean(value = "bookDao1")
public BookDao bookDao1() {BookDao bookDao = new BookDao();
bookDao.setLabel("bookDao1");
return bookDao;
}
@Bean(value = "bookDao2")
@Primary
public BookDao bookDao2() {BookDao bookDao = new BookDao();
bookDao.setLabel("bookDao2");
return bookDao;
}
@Bean(value = "bookDao3")
public BookDao bookDao3() {BookDao bookDao = new BookDao();
bookDao.setLabel("bookDao3");
return bookDao;
}
}
主动注入形式是这样的:
@Autowired
@Qualifier(value = “bookDao1”)
private BookDao bookDao3;
依照优先级程序,@Qulifier(bookDao1) > @Primary(bookDao2) > 属性名(bookDao3),最终加载的是名称为 bookDao1 的组件。
@Inject 注解的应用办法
@Inject 注解的应用办法跟 @Autowired 也根本类似,然而须要留神
- 应用前须要导入 jar 包——javax.inject;
- 反对 @Primary 注解,而且因为没有准确匹配,@Primary 的优先级最高;
- 不反对 required=false,即不能注入 null,如果找不到组件必定报错;
- 默认依照类型匹配查找。
例如,上面这容器中有一个 EmployeeDao 组件
@Configuration
public class InjectBeanConfig {@Bean(value = "employeeDao1")
public EmployeeDao employeeDao1() {EmployeeDao employeeDao = new EmployeeDao();
employeeDao.setLabel("1");
return employeeDao;
}
}
主动注入的形式如下
@Inject
private EmployeeDao employeeDao3;
spring 会先按属性名查找名称为 employeDao3 的组件,即 applicationContext.getBean(“employeeDao3”),后果不存在;
而后依照类型查找,即 applicationContext.getBean(EmployeDao.class),找到 employeDao1 组件,胜利注入。
如果容器中有多个同类型组件,例如
@Configuration
public class InjectBeanConfig {@Bean(value = "employeeDao1")
public EmployeeDao employeeDao1() {EmployeeDao employeeDao = new EmployeeDao();
employeeDao.setLabel("1");
return employeeDao;
}
@Bean(value = "employeeDao2")
public EmployeeDao employeeDao2() {EmployeeDao employeeDao = new EmployeeDao();
employeeDao.setLabel("2");
return employeeDao;
}
@Bean(value = "employeeDao3")
public EmployeeDao employeeDao3() {EmployeeDao employeeDao = new EmployeeDao();
employeeDao.setLabel("3");
return employeeDao;
}
}
注入形式还是这样
@Inject
private EmployeeDao employeeDao3;
依然会按属性名和 bean 的名称匹配,即 applicationContext.getBean(“employeeDao3”),找到 employee3,胜利注入。
然而如果其中某个组件加了 @Primary 注解,会疏忽属性名,优先注入,例如
@Configuration
public class InjectBeanConfig {@Bean(value = "employeeDao1")
public EmployeeDao employeeDao1() {EmployeeDao employeeDao = new EmployeeDao();
employeeDao.setLabel("1");
return employeeDao;
}
@Bean(value = "employeeDao2")
@Primary public EmployeeDao employeeDao2() {EmployeeDao employeeDao = new EmployeeDao();
employeeDao.setLabel("2");
return employeeDao;
}
@Bean(value = "employeeDao3")
public EmployeeDao employeeDao3() {EmployeeDao employeeDao = new EmployeeDao();
employeeDao.setLabel("3");
return employeeDao;
}
}
无论注入时应用什么样的属性名,都会注入 employeeDao2。
@Resource 注解的应用办法
@Resource 注解的应用跟 @Autowired 注解相似,然而须要留神:
- 不反对 @Primary 注解,也不反对 reuqired=false,即不容许注入 null;
- 该注解有一个属性 name,相似于 @Qualified 精准匹配,优先级最高;
- 默认依照属性名跟 bean 的名称匹配查找,如果不存在,再按类型匹配查找。
例如,上面这个容器中有两个 CarDao 组件
@Configuration
@ComponentScan(basePackages = {"cn.monolog.service"})
public class ResourceBeanConfig {@Bean(value = "carDao1")
public CarDao carDao1() {CarDao carDao = new CarDao();
carDao.setLabel("1");
return carDao;
}
@Bean(value = "carDao2")
public CarDao carDao() {CarDao carDao = new CarDao();
carDao.setLabel("2");
return carDao;
}
}
主动注入形式如下,会按属性名注入 carDao2 组件。
// 主动注入
@Resource
private CarDao carDao2;
然而改为上面这种注入形式:
// 主动注入
@Resource(name = “carDao1”)
private CarDao carDao2;
因为应用了 name 精准匹配,会疏忽属性名,注入 carDao1 组件。