@Autowired的实现原理

@Autoeired是通过bean的后置处理器进行解析        

什么是@Autowired表示某个属性是否需要进行依赖注入,可以写在属性和方法上,注解中的required属性默认为true,表示如果没有对象可以注入给属性则抛异常

核心代码:postProcessProperties

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
//1.获取当前类中标注了@Autowired的成员变量和方法的参数封装在metadata对象里
        InjectionMetadata metadata = this.findAutowiringMetadata(beanName, bean.getClass(), pvs);
 
        try {
//2.利用反射赋值
            metadata.inject(bean, beanName, pvs);
            return pvs;
        } catch (BeanCreationException var6) {
            throw var6;
        } catch (Throwable var7) {
            throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", var7);
        }
    }

postProcessProperties()方法的处理流程:

1.调用findAutowiringMetadata()方法,尝试从缓存injectionMetadataCache中获取对应的注入元信息,如果缓存不存在,将会执行buildAutowiringMetadata()获取;
2.循环InjectionMetadata的injectedElements属性,挨个调用InjectionMetadata.InjectedElement.inject方法,通过反射方式设置属性的值

 public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
        //metadata中的数据放在集合中
        Collection<InjectionMetadata.InjectedElement> checkedElements = this.checkedElements;
 
       Collection<Injectio
nMetadata.InjectedElement> elementsToIterate = checkedElements != null ? checkedElements : this.injectedElements;
 
        if (!((Collection)elementsToIterate).isEmpty()) {
            Iterator var6 = ((Collection)elementsToIterate).iterator();
//遍历集合拿到标注了@AutoWired的成员变量和方法
            while(var6.hasNext()) {
                InjectionMetadata.InjectedElement element = (InjectionMetadata.InjectedElement)var6.next();
//遍历调用内部类的方法完成属性赋值
                element.inject(target, beanName, pvs);
            }
        }
 
    }
1.当@Autowired写在属性上时:

@Autowired加在某个属性上,Spring在进行Bean的声明周期过程中,在属性填充这一步,会基于实例化出来的对象,该对象中加了@Autowired的属性自动给属性赋值

spring会根据属性的类型去spring容器中找出该类型的所有的Bean对象,如果找出来多个,则根据属性的名字从多个中确定一个。如果required属性为true,并且根据属性信息找不到对象,则直接抛出异常,

findAutowiringMetadata()方法返回metadata对象

  private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
        //获取当前bean的名称
        String cacheKey = StringUtils.hasLength(beanName) ? beanName : clazz.getName();
       //在缓存中查找是否有当前类的信息
 InjectionMetadata metadata = (InjectionMetadata)this.injectionMetadataCache.get(cacheKey);
        if (InjectionMetadata.needsRefresh(metadata, clazz)) {
            synchronized(this.injectionMetadataCache) {
                metadata = (InjectionMetadata)this.injectionMetadataCache.get(cacheKey);
                if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                    if (metadata != null) {
                        metadata.clear(pvs);
                    }
                //调用此方法解析当前类,获得所有标注@AutoWired的字段 并存入metada中
                    metadata = this.buildAutowiringMetadata(clazz);
                //存入缓存中
                    this.injectionMetadataCache.put(cacheKey, metadata);
                }
            }
        }
        //返回得到@AutoWired的字段的metadata
        return metadata;
    }
2.当@Autowired写在方法上时

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

3.当@Autowired写在构造方法上时:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值