@Autowired注解使用及原理

使用说明

数组或集合的注入

  Spring容器中所有了类型匹配的bean都被注入进来,并且如果bean有@Order注解或者实现Order接口,按照Order的先后顺序注入;

Map的注入
  • key的类型必须为String,注入后值为bean的名称;
  • value类型即为想要注入的bean类,所有类型匹配的bean会被注入进来;

In case of a {@link java.util.Collection} or {@link java.util.Map} dependency type, the container autowires all beans matching the declared value type. For such purposes, the map keys must be declared as type String which will be resolved to the corresponding bean names. Such a container-provided collection will be ordered, taking into account {@link org.springframework.core.Ordered}/{@link org.springframework.core.annotation.Order} values of the target components, otherwise following their registration order in the container. Alternatively, a single matching target bean may also be a generally typed {@code Collection} or {@code Map} itself, getting injected as such.

父类属性的注入

  应用场景:父类或抽象类中存在公共依赖的bean时;

public abstract class AbstractTest {
    @Autowired
    private TestService1 testService1;

    public abstract void test();

    public TestService1 getTestService1() {
        return testService1;
    }

    public void setTestService1(TestService1 testService1) {
        this.testService1 = testService1;
    }
}
@Component
public class TestImpl extends AbstractTest{

    @Autowired
    private TestService2 testService2;

    public TestImpl(){
        System.out.println("TestImpl()");
    }

    @Override
    public void test() {
        testService2.t2();
        TestService1 testService1 = this.getTestService1();
        testService1.t1();
    }
}
required属性

  required属性值可以为true( 默认值)和false。如果为true的话,没有匹配的类则抛出异常;如果为false,则表示不是强制必须能够找到相应的类,无论是否注入成功,都不会抛错。

工作原理

 注解解析器:AutowiredAnnotationBeanPostProcessor

  1. Spring容器启动时,AutowiredAnnotationBeanPostProcessor被注册到容器;
  2. 扫描代码,如果带有@Autowired注解,则将依赖注入信息封装到InjectionMetadata中(见扫描过程);
  3. 创建bean时(实例化对象和初始化),会调用各种BeanPostProcessor对bean初始化,AutowiredAnnotationBeanPostProcessor负责将相关的依赖注入进来;

@Autowired扫描过程

  1. 扫描当前类中标注@Autowired的属性和方法;
  2. 再查找父类中注@Autowired的属性和方法,依次遍历;
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
		LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
		Class<?> targetClass = clazz;

		do {
			final LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<>();

			ReflectionUtils.doWithLocalFields(targetClass, field -> {
				AnnotationAttributes ann = findAutowiredAnnotation(field);
				if (ann != null) {
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isWarnEnabled()) {
							logger.warn("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}
					boolean required = determineRequiredStatus(ann);
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});

			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
					return;
				}
				AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
				if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
					if (Modifier.isStatic(method.getModifiers())) {
						if (logger.isWarnEnabled()) {
							logger.warn("Autowired annotation is not supported on static methods: " + method);
						}
						return;
					}
					if (method.getParameterCount() == 0) {
						if (logger.isWarnEnabled()) {
							logger.warn("Autowired annotation should only be used on methods with parameters: " +
									method);
						}
					}
					boolean required = determineRequiredStatus(ann);
					PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
					currElements.add(new AutowiredMethodElement(method, required, pd));
				}
			});

			elements.addAll(0, currElements);
			targetClass = targetClass.getSuperclass();
		}while (targetClass != null && targetClass != Object.class);

参考:

  1. https://juejin.im/entry/5ad3fda5f265da238d512a98
  • 17
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值