前言
SpringBoot 中通过注解实现依赖注入主要有以下几种:
@Autowired
注解
@Qualifier
注解
@Resource
注解
@Primary
注解
@Autowired: 注入依赖对象
简介
作用
实现依赖注入
查找方式
@Autowired是先到容器查找类型,如果该类型只有一个那么就直接注入,有多个时再根据名字找
使用范围
构造器、方法、参数、字段、注解
参数
required
-> 标注的对象是否必须注入,可能这个对象在容器中不存在,如果为true的时候,找不到匹配的候选者就会报错,为false的时候,找不到也没关系,不会报错
定义
@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;
}
CONSTRUCTOR:构造
METHOD:方法
PARAMETER:参数
FIELD:字段
ANNOTATION_TYPE: 注解
使用示例
1、用于构造方法
将@Autowired注解应用于构造函数,通过构造器注入依赖对象
public class Service {
private Service1 service1;
public Service(){
System.out.println(this.getClass() + "无参构造器");
}
@Autowired
public Service(Service1 service1){
System.out.println(this.getClass() +"有参构造器");
this.service1 = service1;
}
}
2、用于普通方法
将@Autowired标注在方法,spring从容器中查找方法参数相关的bean,然后注入依赖的对象,如果该方法有多个参数,默认多个参数都可以自动注入依赖
@Component
public class Service {
private Service1 service1;
private Service2 service2;
@Autowired
public void injectService1(Service1 service1){
this.service1 = service1;
}
@Autowired
public void injectService1(Service1 service1, Service2 service2){
this.service1 = service1;
this.service2 = service2;
}
}
3、用于setter方法
可能通过构造器,和通过普通的一个方法注入,这两种方式不是很常见,可以将@Autowired标注在set方法上面来注入指定的对象,如下所示
@Component
public class Service {
private Service1 service1;
@Autowired
public void setService1(Service1 service1){
this.service1 = service1;
}
}
4、用于方法参数上
@Autowired直接标注于方法的具体参数上,在多个参数的时候,方法上面的@Autowired默认对方法中所有的参数起效,如果我们想对其中某个参数进行特定的配置,则有以下两种方法实现:
1、可以在需依赖注入的参数前面加上@Autowired,就能实现自动依赖注入。
@Component
public class Service {
private Service1 service1;
private String name;
public void injectService(@Autowired Service1 service1, String name){
this.service1 = service1;
this.name = name;
}
此时方法的第一个参数则受到@Autowired约束,而第二个参数则不受约束
2、在不需要强制注入的参数前面加@Autowired,并设置required为false,这样则表示这个bean不是强制注入,能找到相应的bean就注入,找不到的话就注入一个null对象,如下 :
@Component
public class Service {
private Service1 service1;
private String name;
@Autowired
public void injectService(Service1 service1, @Autowired(required = false) String name){
this.service1 = service1;
this.name = name;
}
}
此时方法的第一参数被上面的@Autowired约束,第二个参数受@Autowired(required=false)
约束
5、用于字段上
@Autowired直接标注于具体的字段,则会自动进行依赖注入,Spring会去容器中按照类型查找相关类型的bean,然后将设置到相应的属性。
@Component
public class Service {
@Autowired
private Service1 service1;
}
6、用于Collection、Map中
1、注入到Collection中,被注入的类型为Collection类型或者Collection子接口类型,注意必须是接口类型
Collection<IService>
List<IService>
Set<IService>
2、注入到Map中,被注入的类型为Map类型或者Map子接口类型,注意必须是接口类型
Map<String,IService>
示例如下:
下面分别先定义一个接口,两个接口的实现类
public interface IService {
}
@Component
public class Service1 implements IService {
}
@Component
public class Service2 implements IService {
}
@Component
public class Service {
@Autowired
private List<IService> services; //@1
@Autowired
private Map<String, IService> serviceMap; //@2
}
@1: 注入IService类型的所有bean
@2: 注入一个map
@Resource:注入依赖对象
简介
作用
和@Autowired注解类似,也是用来注入依赖对象的,spring容器会对bean中所有的字段、方法进行遍历,标注有@Resouce注解的,都会进行注入。@Autowired是在javax中定义的注解,并不是spring中定义的注解。
查找方式
@Resource是先到容器按照名字查找,同一名字只有一个则直接注入,同名不同类时则再按照类型查找。
使用范围
任何类型、字段、方法
定义
@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
public @interface Resource {
String name() default "";
..其他不常用的参数省略
}
使用示例
1、用于字段
@Component
public class Service2 {
@Resource
private Service1 service1;
}
2、用于方法
@Component
public class Service {
private Service1 service1;
@Resource
public void setService1(Service1 service1){
this.service1 = service1;
}
}
3、用于Collection、Map中
1、注入到Collection中,被注入的类型为Collection类型或者Collection子接口类型,注意必须是接口类型
Collection<IService>
List<IService>
Set<IService>
2、注入到Map中,被注入的类型为Map类型或者Map子接口类型,注意必须是接口类型
Map<String,IService>
下面分别先定义一个接口,两个接口的实现类
public interface IService {
}
@Component
public class Service {
@Resource
private List<IService> services; //@1
@Resource
private Map<String, IService> serviceMap; //@2
}
@1: 注入IService类型的所有bean
@2: 注入一个map
@Qualifier: 限定符
简介
作用
可以在依赖注入查找候选者的过程中对候选者进行过滤,比如:在需要自动注入java bean时,如果注入的是一个接口,而这个接口又有多个实现类,则会报错,解决方法是在注入接口上增加@Qualifier(“别名”) 和@Autowired注解,
使用范围
字段、方法、参数、任意类型、注解
参数
value
定义
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Qualifier {
String value() default "";
}
使用示例
1、用于类上
用在类上,你可以理解为给通过@Qulifier给这个bean打一个标签
public interface IService { }
@Component
@Qualifier("tag1") //@1
public class Service1 implements IService{ }
@1: 设置@Qulifier的value为tag1
@Component
@Qualifier("tag2") //@2
public class Service2 implements IService { }
@2: 设置@Qulifier的value为tag2
@Component
@Qualifier("tag3") //@3
public class Service3 implements IService { }
@3: 设置@Qulifier的value为tag3
@Component
public class InjectService {
@Autowired
@Qualifier("tag1") //@1
private Map<String, IService> serviceMap1;
@Autowired
@Qualifier("tag2") //@2
private Map<String, IService> serviceMap2;
@Autowired
@Qualifier("tag3") //@3
private Map<String, IService> serviceMap3;
}
@1: 限定符的值为tag1,此时会将类上限定符为tag1的所有bean注入进来
@2: 限定符的值为tag2,此时会将类上限定符为tag2的所有bean注入进来
@3: 限定符的值为tag3,此时会将类上限定符为tag3的所有bean注入进来
2、结合@Autowired使用
我们先定义一个接口,以及两个实现类,分别是Servicr1和Service2
public interface IService { }
@Component
@Qualifier("service1")
public class Service1 implements IService{ }
@Component
@Qualifier("service2")
public class Service2 implements IService { }
@Component
public class InjectService {
@Autowired
@Qualifier("service2") //@1
private IService service;
}
@1: 这里限定符的值为service2,容器中IService类型的bean有2个【service1,service2】,当类上没有标注@Qualifier注解的时候,可以理解为:bean的名称就是限定符的值,所以@1这里会匹配到service2
3、用于方法参数
public interface IService { }
@Component
@Qualifier("service1")
public class Service1 implements IService{ }
@Component
@Qualifier("service2")
public class Service2 implements IService { }
@Component
public class InjectService {
private IService s1;
private IService s2;
@Autowired
public void injectBean(@Qualifier("service2") IService s1, @Qualifier("service1") IService s2) { //@1
this.s1 = s1;
this.s2 = s2;
}
}
@1: 方法上标注了@Autowired注解,说明会被注入依赖,2个参数上分别使用了限定符来指定具体需要注入哪个bean
4、用在setter方法上
不管是用在setter方法还是普通方法上面,都是一样的效果
public interface IService { }
@Component
@Qualifier("service1")
public class Service1 implements IService{ }
@Component
@Qualifier("service2")
public class Service2 implements IService { }
@Component
public class InjectService {
private IService s1;
private IService s2;
@Autowired
@Qualifier("service2")
public void setS1(IService s1) {
this.s1 = s1;
}
@Autowired
@Qualifier("service1")
public void setS2(IService s2) {
this.s2 = s2;
}
}
上面2个setter方法上都有@Autowired注解,并且结合了@Qulifier注解来限定需要注入哪个bean
@Primary: 设置为主要候选者
简介
作用
在注入依赖的过程中,当有多个候选者的时候,可以指定哪个候选者为主要的候选者。可以用在类上或者方法上面。通常定义bean常见的有2种方式:
1、在类上标注@Component注解,此时可以配合@Primary,标注这个bean为主要候选者。
2、在配置文件中使用@Bean注解标注方法,来注册bean,可以在@Bean标注的方法上加上@Primary,标注这个bean为主要候选bean。
使用范围
类、方法
参数
value
定义
定义
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Primary { }
使用示例
1、用于类上
public interface IService { }
@Component
public class Service1 implements IService{ }
@Component
@Primary //此处使用了@Primary,表示这是个主要候选者
public class Service2 implements IService { }
@Component
public class InjectService {
@Autowired
private IService service1; //@1
}
2、用于方法上
public interface IService { }
//注意,这个类没有标注@Component 注解的,表明这个类并非是自动依赖注入
public class Service1 implements IService { }
//注意,这个类没有标注@Component 注解的,表明这个类并非是自动依赖注入
public class Service2 implements IService { } //注意,这个类没有标注@Component 注解的,表明这个类并非是自动依赖注入
//该类为一个配置类,主要是通过定义Bean注解来实现相关类的依赖注入
@Configuration
public class ServiceConfig{
@Bean
public IService service1() {
return new Service1();
}
@Bean
@Primary //这个bean被标注为主要的候选者
public IService service2() {
return new Service2();
}
}
public class InjectService {
@Autowired
private IService service;//@1
}
@1:IService为两个实现类,同进在ServiceConfig中,两个实现类Service1、Service2都实现在依赖注入,而此时由于Service2的bean使用了@Primary注解,因此在查找到多个Bean时,会优化选择有@Primary标注的bean进行注入,所以在这里service注入的值是Service2
原创文章,作者:jiafegn,如若转载,请注明出处:https://www.techlearn.cn/archives/2018