@Autowired原理

一、@Autowired注解的用法

         1.@Autowired注解应用于构造方法,示例如下:


public class Student {
    private String name;

    public Student() {
    }
    @Autowired
    public Student(String name) {
        this.name = name;
    }
}

 @Autowired加在构造方法上时,Spring会在推断构造方法阶段,选择该构造方法来进行实例化,在反射调用构造方法之前,会先根据构造方法参数类型、参数名从Spring容器中找到Bean对象,当做构造方法入参。

        2.@Autowired注解应用于属性上,示例如下:

public class Student {
    private String name;
    @Autowired
    private IBanjiMapper banji;
  
}

 @Autowired加在某个属性上,Spring在进行Bean的生命周期过程中,在属性填充这一步,会基于实例化出来的对象,对该对象中加了@Autowired的属性自动给属性赋值。Spring会先根据属性的类型去Spring容器中找出该类型所有的Bean对象,如果找出来多个,则再根据属性的名字从多个中再确定一个,如果required属性为true,并且根据属性信息找不到对象,则直接抛异常。
    3.@Autowired注解应用于方法上,示例如下:


@Autowired
public void setUserService(UserService userService){
    this.userService = userService;
}

  @Autowired注解写在某个方法上时,Spring在Bean生命周期的属性填充阶段,会根据方法的参数类型、参数名字从Spring容器找到对象当做方法入参,自动反射调用该方法。

二、@Autowired注解自动装配的过程

@Autowired:默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用(Spring提供)

@Qualifier():指定装配的bean,多个实例时可以结合@Autowired一起使用

@Primary:自动装配时当出现多个bean候选者时,被注解为@Primary的bean将作为首选者

@Resource:默认按名称装配,当找不到与名称匹配的bean才会按类型装配

@Autowired通过Bean的后置处理器进行解析的

 1.在创建一个Spring上下文的时候在构造函数中进行注册AutowiredAnnotationBeanPostProcessor

 2.在Bean的创建过程中进行解析:

          2.1预解析(解析@Autowired标注的属性、方法, 比如:把属性的类型、名称、属性所在的类...元数据缓存起来;

          2.2在属性注入真正的解析(拿到上一步缓存的元数据去IOC容器进行查找,并且返回注入);

                a.首先根据预解析的元数据拿到类型去容器中进行查找:

                        · 如果查询结果没有可以与之匹配的类,则会报异常 NoSuchBeanDefinitionException

                        · 如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据;

                        · 如果查询结果不止一个,那么@Autowired会根据名称来查找,如果还没有则会报错NoUniqueBeanDefinitionException


三、源码追踪

这里对@Autowired注解底层进行源码分析

@Autowired是用来装配bean的,肯定和bean的实例化有关,先经过了refresh方法,在finishBeanFactoryInitialization方法中getBean,然后走getObject的时候触发bean的初始化。bean的初始化是一个很复杂地方,在AbstractAutowireCapableBeanFactory#doCreateBean方法中,先创建一个BeanWrapper,它的内部成员变量wrappedObject中存放的就是实例化的MyService对象,[Spring Bean的生命周期源码详解 - 【Spring底层原理】,再往后进入populateBean方法进行属性注入

Spring对autowire注解的实现逻辑位于类:AutowiredAnnotationBeanPostProcessor#postProcessProperties之中,——>findAutowiringMetadata——>buildAutowiringMetadata,核心代码就在buildAutowiringMetadata方法里面

private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
        if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
            return InjectionMetadata.EMPTY;
        } else {
            List<InjectedElement> elements = new ArrayList();
               // 需要处理的目标类
            Class targetClass = clazz;

            do {
                List<InjectedElement> currElements = new ArrayList();
            // 通过反射获取该类所有的字段,并遍历每一个字段,并通过方法 
       //findAutowiredAnnotation遍历每一个字段的所用注解,并如果用autowired修饰了,则返回 
     // auotowired相关属性
                ReflectionUtils.doWithLocalFields(targetClass, (field) -> {
                    MergedAnnotation<?> ann = this.findAutowiredAnnotation(field);
                    if (ann != null) {
                // 校验autowired注解是否用在了static方法上
                        if (Modifier.isStatic(field.getModifiers())) {
                            if (this.logger.isInfoEnabled()) {
                                this.logger.info("Autowired annotation is not supported on static fields: " + field);
                            }

                            return;
                        }
                    // 判断是否指定了required
                        boolean required = this.determineRequiredStatus(ann);
                        currElements.add(new AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement(field, required));
                    }

                });

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值