【七】Spring IoC 最全源码详解之bean的依赖注入

上篇文章,我在开头将bean实例化过程比喻成寒武纪生命大爆发。如果你同意这个看法的话,那本文解析的bean的依赖注入就是生命的形式生物从两栖进化到爬行,从爬行进化到哺乳,从哺乳进化到类人猿,从低等进化到高等的过程。本文撰写累计时常10小时,建议阅读时间5小时。去趟卫生间,等你回来我们就开始吧。目录1. applyMergedBeanDefinitionPostProcessors...
摘要由CSDN通过智能技术生成

上篇文章,我在开头将bean实例化过程比喻成寒武纪生命大爆发。如果你同意这个看法的话,那本文解析的bean的依赖注入就是生命的形式生物从两栖进化到爬行,从爬行进化到哺乳,从哺乳进化到类人猿,从低等进化到高等的过程。

本文撰写累计时常10小时,建议阅读时间5小时。去趟卫生间,等你回来我们就开始吧。


目录

1. applyMergedBeanDefinitionPostProcessors

1.1 CommonAnnotationBeanPostProcessor

1.2 AutowiredAnnotationBeanPostProcessor

2. populateBean

3. postProcessProperties方法

3.1 CommonAnnotationBeanPostProcessor方法的inject

3.1.1 doResolveDependency

3.1.2 String类型的依赖注入

3.1.3 普通类型的依赖注入

3.2 AutowiredAnnotationBeanPostProcessor方法的inject

4. 构造函数注入

5. 附录:本项目工程文件


上一篇文章,已经详细分析了bean的实例化过程。也就是doCreatBean方法中instanceWrapper = createBeanInstance(beanName, mbd, args);执行完成,将实例化后的bean封装在了wrapper中。随后再解封出来bean对象和bean对应的类型。接下来调用applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);方法。

1. applyMergedBeanDefinitionPostProcessors

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
        throws BeanCreationException {    
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }

    // 从BeanWrapper获得封装在它内部的bean和bean类型
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }
    // 调用实现了MergedBeanDefinitionPostProcessor的bean后置处理器的postProcessMergedBeanDefinition方法。
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {                
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }
            catch (Throwable ex) {
                throw new xxx;
            }
            // 标记该bd已经合并处理完成了
            mbd.postProcessed = true;
        }
    }
    // 加入到bean工厂的earlySingletonObjects中,这个是Spring用来解决循环依赖的凭据(后续文章单独介绍循环依赖)
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {        
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }    
    Object exposedObject = bean;
    try {        
        // 依赖注入填充属性
        populateBean(beanName, mbd, instanceWrapper);
        // bean属性填充完成后,就可以进行bean的初始化工作了。依赖注入初始化工作后续文章再详细介绍。
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    catch (Throwable ex) {
        throw new xxx;
    }

    if (earlySingletonExposure) {
        Object earlySingletonReference = getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                if (!actualDependentBeans.isEmpty()) {
                    throw new xxx;
                }
            }
        }
    }
    // 注册实现了DisposableBean接口的bean,该bean实现了void destroy()接口,在bean的生命周期销毁前可以触发回调进行善后工作。
    // 需要注意的是,它对原型对象无效。
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new xxx;
    }
    return exposedObject;
}

调用实现了MergedBeanDefinitionPostProcessor的bean后置处理器的postProcessMergedBeanDefinition方法,其中有用到的后置处理器是CommonAnnotationBeanPostProcessor, AutowiredAnnotationBeanPostProcessor, ApplicationListenerDetector。

1.1 CommonAnnotationBeanPostProcessor

CommonAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法如下:

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {    
    super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
    // 解析bean属性上@Resource的注解,将其封装为metadata对象并缓存
    InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
    // 对注入的metadata对象进行检查,没有注册的bd需要进行注册。最后添加到metadata对象的checkedElements集合中。
    metadata.checkConfigMembers(beanDefinition);
}

 super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);中处理@PostConstruct 和 @PreDestroy方法添加到InitDestroyAnnotationBeanPostProcessor的lifecycleMetadataCache这个CurrentHashMap中,该map中的存放的结果是<Class<?>, LifecycleMetadata>。LifecycleMetadata对象中封装了initMethods和destroyMethods方法,与之对应的是@PostConstruct 和 @PreDestroy注解的两类方法。通过class类名就能得到该声明周期回调对象。

metadata.checkConfigMembers(beanDefinition);对注入的medadata对象进行检查,没有注册的bd需要进行注册。最后添加到metadata对象的checkedElements集合中。

核心代码是findResourceMetadata(beanName, beanType, null);

InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) {    
    String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    // 缓存中如果没有,则创建一个metadata
    InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    if (InjectionMetadata.needsRefresh(metadata, clazz)) {
        synchronized (this.injectionMetadataCache) {
            metadata = this.injectionMetadataCache.get(cacheKey);
            if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                if (metadata != null) {
                    metadata.clear(pvs);
                }
                metadata = buildResourceMetadata(clazz);
                this.injectionMetadataCache.put(cacheKey, metadata);
            }
        }
    }
    return metadata;
}

它的核心是buildResourceMetadata(clazz);它会沿着类及其父类解析出添加了@WebServiceRef, @EJB, @Resource注解的属性和方法,将其加入到elements中。然后将clazz和elements封装成一个InjectionMetadata对象findResourceMetadata方法。findResourceMetadata会将metadata对象缓存在commonAnnotationBeanPostProcessor后置处理器对象的injectionMetadataCache map中方便后续流程使用。

private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
    List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    Class<?> targetClass = clazz;
    // 沿着class的继承路径,按层次寻找加上了@WebServiceRef, @EJB, @Resource注解的属性和方法,将其加入到currElements中。
    do {
        final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
        // 遍历Class中的所有field,判断每个field是否需要被注入
        // 如果上述注解加在静态类,静态方法,会直接报错!
        ReflectionUtils.doWithLocalFields(targetClass, field -> {
            if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {                
                currElements.add(new WebServiceRefElement(field, field, null));
            }
            else if (ejbRefClass != null && field.isAnnotationPresent(ejbRefClass)) {                
                currElements.add(new EjbRefElement(field, field, null));
            }
            else if (field.isAnnotationPresent(Resource.class)) {
                if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
                    currElements.add(new ResourceElement(field, field, null));
                }
            }
        });
        // 遍历Class中的所有method,判断每个method是否需要依赖项
        ReflectionUtils.doWithLocalMethods(targetClass, method -> {
            Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
            if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                return;
            }
            if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {
                    PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                    currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));
                }
                else if (ejbRefClass != null && bridgedMethod.isAnnotationPresent(ejbRefClass)) {
                    PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                    currElements.add(new EjbRefElement(method, bridgedMethod, pd));
                }
                else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
                    if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
                        PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                        //new的是一个ResourceElement实例,它是InjectionMetadata.InjectedElement的子类
                        currElements.add(new ResourceElement(method, bridgedMethod, pd));
                    }
                }
            }
        });
        // 将上面找到的currElements添加到elements中。
        elements.addAll(0, currElements);
        targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class);

    return new InjectionMetadata(clazz, elements);
}

1.2 AutowiredAnnotationBeanPostProcessor

AutowiredAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法如下,核心方法是findAutowiringMetadata。

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
    metadata.checkConfigMembers(beanDefinition);
}


private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
    String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    // 缓存中如果没有,则创建一个metadata
    InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    if (InjectionMetadata.needsRefresh(metadata, clazz)) {
        synchronized (this.injectionMetadataCache) {
            metadata = this.injectionMetadataCache.get(cacheKey);
            if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                if (metadata != null) {
                    metadata.clear(pvs);
                }
                metadata = buildAutowiringMetadata(clazz);
                this.injectionMetadataCache.put(cacheKey, metadata);
            }
        }
    }
    return metadata;
}

与findResourceMetadata中核心方法是是调用buildResourceMetadata类似,在findAutowiringMetadata中核心方法是调用buildAutowiringMetadata。最终也会将需要注入的属性或方法添加到elements中。并且返回封装好的metadata对象。上层也会将其缓存到injectionMetadataCache中。

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
    List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    Class<?> targetClass = clazz;

    do {
        final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
        // 遍历Class中的所有field,根据注解判断每个field是否需要被
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值