这些注解都是用于标识需要spring容器注入bean。
@Autowired, @Qualifier, @Primary是spring自带的注解
@Resource, @Inject是JSR 250注解,是javaee规范。spring进行了实现。
@Autowired
源码如下
package org.springframework.beans.factory.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
boolean required() default true;
}
@Autowired注解说明
- 该注解可以加在构造器,方法,方法参数,成员变量和注解上
- 只有一个属性:required, 默认true。 当为true,DI找不到对应的bean时会抛出异常。
- 默认优先按照类型去容器找对应的组件
- 如果找到多个类型匹配的组件,再根据属性名称作为bean name去容器中查找
@Qualifier
配合@Autowired注解使用,当@Autowired想明确指定bean name时通过@Qualifier设置。
@Qualifier源码:
package org.springframework.beans.factory.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Qualifier {
String value() default "";
}
@Qualifier因为跟@Autowired搭配使用,不会单独使用,所以能加注的地方跟@Autowired一致。
@Primary
当出现多个同类型的bean时,如果某个bean上加注了@Primary时,其他地方使用类型注入时会优先使用该bean。
源码如下:
package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Primary {
}
@Autowired, @Qualifier, @Primary综合示例
package win.elegentjs.spring.ioc.di.autowired;
import lombok.Data;
@Data
public class Bird {
private String name;
}
package win.elegentjs.spring.ioc.di.autowired;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
/**
* Person类注入两个field, 两个都使用@Autowired注入
* 一个指定了bean name
* 另一个未指定,按类型注入
*/
@Data
public class Person {
@Autowired
@Qualifier("bird")
private Bird bird;
@Autowired
private Bird anotherBird;
}
定义java config类
package win.elegentjs.spring.ioc.di.autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
/**
* java config配置类
*/
@Configuration
public class AutowiredConfig {
/**
* 定义bean name 为bird的bean
*/
@Bean
public Bird bird() {
Bird b = new Bird();
b.setName("鹦鹉");
return b;
}
/**
* 定义bean name 为bird2的bean,标注了@Primary。当按类型注入该bean时会优先注入
*/
@Bean
@Primary
public Bird bird2() {
Bird b = new Bird();
b.setName("鹦鹉2");
return b;
}
@Bean
public Person person() {
return new Person();
}
}
执行看看结果:
package win.elegentjs.spring.ioc.di.autowired;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@Slf4j
public class AutowiredSample {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AutowiredConfig.class);
Person p = context.getBean(Person.class);
log.info("==> p: {}", p);
}
}
// result:
2021-06-03 14:00:52.551 [main] INFO w.e.spring.ioc.di.autowired.AutowiredSample-==> p: Person(bird=Bird(name=鹦鹉), anotherBird=Bird(name=鹦鹉2))
从结果可以看出当明确了bean name时会按匹配bean name的bean注入,当未指定明确的bean name时优先注入@Primary的bean。
@Resource
@Resource是 JavaEE JSR250标准规范的注解,默认按照bean name注入,bean name可以通过注入属性name指定,未指定默认按字段名查找。如果未指定name,且字段名作为bean name也找不到,才会按类型注入。
@Inject
@Inject注解是JSR330标准规范提供的注解,默认按照属性名查找bean, 支持@Primary。可以增加@Named注解指定注入的bean。
@Autowired vs @Resource vs @Inject
- @Autowired时spring专有注解。@Resource是JSR规范,@Inject是JSR330规范
- @Autowired支持required参数,其他两个不支持
- @Autowired, @Inject支持@Primary优先注入功能,@Resource不支持
- @Autowired搭配@Qulifier指定bean name, @Resource通过属性name指定,@Inject通过@Named注解支持
推荐统一使用@Autowired注解。