0
点赞
收藏
分享

微信扫一扫

Spring:bean的生命周期与@Autowire(2)

Gascognya 2022-05-02 阅读 85
spring

参考资料:

《Spring IoC源码学习:@Autowire 详解》

全系列文章:

《Spring:bean的生命周期与@Autowire(1)》

目录

一、AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors

二、AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

        1、findAutowiringMetadata

         2、buildAutowiringMetadata

        3、checkConfigMembers

三、InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation

四、AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues


写在开头:本文为学习后的总结,可能有不到位的地方,错误的地方,欢迎各位指正。

       

        前文中我们走完了createBeanInstance的流程,完成了bean的实例化,本文中我们继续走完后续的流程。

一、AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors

        doCreateBean继续往下走,就到了applyMergedBeanDefinitionPostProcessors方法。

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
        throws BeanCreationException {
 
    // 1、实例化bean
    instanceWrapper = createBeanInstance(beanName, mbd, args);

    // 2、应用后置处理器MergedBeanDefinitionPostProcessor,允许修改MergedBeanDefinition
    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}

         调用applyMergedBeanDefinitionPostProcessors方法,遍历MergedBeanDefinitionPostProcessor接口的实现类,调用postProcessMergedBeanDefinition方法。

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
    // 1.获取BeanFactory中已注册的BeanPostProcessor
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof MergedBeanDefinitionPostProcessor) {
            // 2.调用MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法,
            // 对指定bean的给定MergedBeanDefinition进行后置处理,@Autowire注解在这边对元数据进行预解析
            MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
            bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
        }
    }
}

        前文中我们了解到,AutowiredAnnotationBeanPostProcessor也是接口的实现类,因此这里也会调用该类的方法。

二、AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    if (beanType != null) {
        // 1.在指定Bean中查找使用@Autowire注解的元数据
        InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
        // 2.检查元数据中的注解信息
        metadata.checkConfigMembers(beanDefinition);
    }
}

        1、findAutowiringMetadata

         findAutowiringMetadata方法会查找当前bean的InjectionMetadata缓存,如果没有,则调用buildAutowiringMetadata方法生成。

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, PropertyValues pvs) {
    // Fall back to class name as cache key, for backwards compatibility with custom callers.
    // 1.设置cacheKey的值(beanName 或者 className)
    String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    // Quick check on the concurrent map first, with minimal locking.
    // 2.检查beanName对应的InjectionMetadata是否已经存在于缓存中
    InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    // 3.检查InjectionMetadata是否需要刷新(为空或者class变了)
    if (InjectionMetadata.needsRefresh(metadata, clazz)) {
        synchronized (this.injectionMetadataCache) {
            // 4.加锁后,再次从缓存中获取beanName对应的InjectionMetadata
            metadata = this.injectionMetadataCache.get(cacheKey);
            // 5.加锁后,再次检查InjectionMetadata是否需要刷新
            if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                if (metadata != null) {
                    // 6.如果需要刷新,并且metadata不为空,则先移除
                    metadata.clear(pvs);
                }
                try {
                    // 7.解析@Autowired注解的信息,生成元数据(包含clazz和clazz里解析到的注入的元素,
                    // 这里的元素包括AutowiredFieldElement和AutowiredMethodElement)
                    metadata = buildAutowiringMetadata(clazz);
                    // 8.将解析的元数据放到injectionMetadataCache缓存,以备复用,每一个类只解析一次
                    this.injectionMetadataCache.put(cacheKey, metadata);
                } catch (NoClassDefFoundError err) {
                    throw new IllegalStateException("Failed to introspect bean class [" + clazz.getName() +
                            "] for autowiring metadata: could not find class that it depends on", err);
                }
            }
        }
    }
    return metadata;
}

         2、buildAutowiringMetadata

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
    // 1.用于存放所有解析到的注入的元素的变量
    LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
    Class<?> targetClass = clazz;
 
    // 2.循环遍历
    do {
        // 2.1 定义存放当前循环的Class注入的元素(有序)
        final LinkedList<InjectionMetadata.InjectedElement> currElements =
                new LinkedList<InjectionMetadata.InjectedElement>();
 
        // 2.2 如果targetClass的属性上有@Autowired注解,则用工具类获取注解信息
        ReflectionUtils.doWithLocalFields(targetClass, new ReflectionUtils.FieldCallback() {
            @Override
            public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
                // 2.2.1 获取field上的@Autowired注解信息
                AnnotationAttributes ann = findAutowiredAnnotation(field);
                if (ann != null) {
                    // 2.2.2 校验field是否被static修饰,如果是则直接返回,因为@Autowired注解不支持static修饰的field
                    if (Modifier.isStatic(field.getModifiers())) {
                        if (logger.isWarnEnabled()) {
                            logger.warn("Autowired annotation is not supported on static fields: " + field);
                        }
                        return;
                    }
                    // 2.2.3 获取@Autowired注解的required的属性值(required:值为true时,如果没有找到bean时,自动装配应该失败;false则不会)
                    boolean required = determineRequiredStatus(ann);
                    // 2.2.4 将field、required封装成AutowiredFieldElement,添加到currElements
                    currElements.add(new AutowiredFieldElement(field, required));
                }
            }
        });
 
        // 2.3 如果targetClass的方法上有@Autowired注解,则用工具类获取注解信息
        ReflectionUtils.doWithLocalMethods(targetClass, new ReflectionUtils.MethodCallback() {
            @Override
            public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
                // 2.3.1 找到桥接方法
                Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
                // 2.3.2 判断方法的可见性,如果不可见则直接返回
                if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                    return;
                }
                // 2.3.3 获取method上的@Autowired注解信息
                AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
                if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                    // 2.3.4 校验method是否被static修饰,如果是则直接返回,因为@Autowired注解不支持static修饰的method
                    if (Modifier.isStatic(method.getModifiers())) {
                        if (logger.isWarnEnabled()) {
                            logger.warn("Autowired annotation is not supported on static methods: " + method);
                        }
                        return;
                    }
                    // 2.3.5 @Autowired注解标识在方法上的目的就是将容器内的Bean注入到方法的参数中,没有参数就违背了初衷
                    if (method.getParameterTypes().length == 0) {
                        if (logger.isWarnEnabled()) {
                            logger.warn("Autowired annotation should only be used on methods with parameters: " +
                                    method);
                        }
                    }
                    // 2.3.6 获取@Autowired注解的required的属性值
                    boolean required = determineRequiredStatus(ann);
                    // 2.3.7  获取method的属性描述器
                    PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                    // 2.3.8 将method、required、pd封装成AutowiredMethodElement,添加到currElements
                    currElements.add(new AutowiredMethodElement(method, required, pd));
                }
            }
        });
 
        // 2.4 将本次循环获取到的注解信息添加到elements
        elements.addAll(0, currElements);
        // 2.5 在解析完targetClass之后,递归解析父类,将所有的@Autowired的属性和方法收集起来,且类的层级越高其属性会被越优先注入
        targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class); // 2.6 递归解析targetClass父类(直至父类为Object结束)
 
    // 2.7 将clazz和解析到的注入的元素封装成InjectionMetadata
    return new InjectionMetadata(clazz, elements);
}

        3、checkConfigMembers

        检查元数据中的注解信息。

public void checkConfigMembers(RootBeanDefinition beanDefinition) {
    Set<InjectedElement> checkedElements = new LinkedHashSet<InjectedElement>(this.injectedElements.size());
    // 1.遍历检查所有要注入的元素
    for (InjectedElement element : this.injectedElements) {
        Member member = element.getMember();
        // 2.如果beanDefinition的externallyManagedConfigMembers属性不包含该member
        if (!beanDefinition.isExternallyManagedConfigMember(member)) {
            // 3.将该member添加到beanDefinition的externallyManagedConfigMembers属性
            beanDefinition.registerExternallyManagedConfigMember(member);
            // 4.并将element添加到checkedElements
            checkedElements.add(element);
            if (logger.isDebugEnabled()) {
                logger.debug("Registered injected element on class [" + this.targetClass.getName() + "]: " + element);
            }
        }
    }
    // 5.赋值给checkedElements(检查过的元素)
    this.checkedElements = checkedElements;
}

        到这里为止,使用 @Autowire 修饰的方法和属性的相关元数据信息都已经放到 injectionMetadataCache 缓存中,用于后续使用。

三、InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation

        完成了@Autowire注解的预解析,doCreateBean流程继续往下走,走到了属性注入方法populateBean(前面还有一步addSingletonFactory方法,这个步骤是为了避免循环依赖二创建的三层缓存,有兴趣的可以看我这篇文章了解下《Spring:如何解决单例bean中的属性循环依赖》)

​
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
        throws BeanCreationException {
 
    // 1、实例化bean
    instanceWrapper = createBeanInstance(beanName, mbd, args);

    // 2、应用后置处理器MergedBeanDefinitionPostProcessor,允许修改MergedBeanDefinition
    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

    // 3、创建三层缓存,为避免循环依赖做准备
	addSingletonFactory(beanName, new ObjectFactory<Object>() {
		@Override
		public Object getObject() throws BeansException {
			return getEarlyBeanReference(beanName, mbd, bean);
		}
	});

    // 4、属性注入
    populateBean(beanName, mbd, instanceWrapper);

    // ...
}

​

        在bean实例化前,我们调用了 InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法,到了属性注入这一步,实例化步骤已经完成了,因此我们需要调用实例化后方法,即postProcessAfterInstantiation。

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {

 
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        // 如果mbd不是合成的 && 存在InstantiationAwareBeanPostProcessor,则遍历处理InstantiationAwareBeanPostProcessor
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                // 在bean实例化后,属性填充之前被调用,允许修改bean的属性,如果返回false,则跳过之后的属性填充
                if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    // 如果返回false,将continueWithPropertyPopulation赋值为false,代表要跳过之后的属性填充
                    continueWithPropertyPopulation = false;
                    break;
                }
            }
        }
    }

}

四、AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues

        populateBean方法中,应用后置处理器 InstantiationAwareBeanPostProcessor 的方法 postProcessPropertyValues,进行属性填充前的再次处理。由于AutowiredAnnotationBeanPostProcessor继承自AutowiredAnnotationBeanPostProcessor,这里便会执行@@Autowire的自动注入。

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {

 
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        // 如果mbd不是合成的 && 存在InstantiationAwareBeanPostProcessor,则遍历处理InstantiationAwareBeanPostProcessor
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                // 在bean实例化后,属性填充之前被调用,允许修改bean的属性,如果返回false,则跳过之后的属性填充
                if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    // 如果返回false,将continueWithPropertyPopulation赋值为false,代表要跳过之后的属性填充
                    continueWithPropertyPopulation = false;
                    break;
                }
            }
        }
    }
    
    // ...

    // 注册过InstantiationAwareBeanPostProcessors 或者 需要依赖检查
    if (hasInstAwareBpps || needsDepCheck) {
        PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        if (hasInstAwareBpps) {
            // 应用后置处理器InstantiationAwareBeanPostProcessor
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    // 应用后置处理器InstantiationAwareBeanPostProcessor的方法postProcessPropertyValues,
                    // 进行属性填充前的再次处理。例子:现在最常用的@Autowire属性注入就是这边注入依赖的bean实例对象
                    pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvs == null) {
                        return;
                    }
                }
            }
        }
        if (needsDepCheck) {
            // 依赖检查,对应depends-on属性
            checkDependencies(beanName, mbd, filteredPds, pvs);
        }
    }

}

@Override
public PropertyValues postProcessPropertyValues(
        PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
 
    // 1.在指定Bean中查找使用@Autowire注解的元数据
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    try {
        // 2.InjectionMetadata: 执行inject()方法,开始执行属性注入或方法注入
        metadata.inject(bean, beanName, pvs);
    } catch (BeanCreationException ex) {
        throw ex;
    } catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
    }
    return pvs;
}
public void inject(Object target, String beanName, PropertyValues pvs) throws Throwable {
    // 1.如果checkedElements存在,则使用checkedElements,否则使用injectedElements
    Collection<InjectedElement> elementsToIterate =
            (this.checkedElements != null ? this.checkedElements : this.injectedElements);
    if (!elementsToIterate.isEmpty()) {
        boolean debug = logger.isDebugEnabled();
        for (InjectedElement element : elementsToIterate) {
            if (debug) {
                logger.debug("Processing injected element of bean '" + beanName + "': " + element);
            }
            // 2.解析@Autowired注解生成的元数据类:AutowiredFieldElement、AutowiredMethodElement,
            // 这两个类继承InjectionMetadata.InjectedElement,各自重写了inject方法。
            element.inject(target, beanName, pvs);
        }
    }
}

         解析 @Autowired 注解生成的元数据类:AutowiredFieldElement、AutowiredMethodElement,这两个类继承InjectionMetadata.InjectedElement,各自重写了 inject 方法。对于属性注入来说,会走到 AutowiredFieldElement 中的 inject 方法。

@Override
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
    // 1.拿到该元数据的属性值
    Field field = (Field) this.member;
    Object value;
    // 2.如果缓存中已经存在,则直接从缓存中解析属性
    if (this.cached) {
        value = resolvedCachedArgument(beanName, this.cachedFieldValue);
    } else {
        // 3.将field封装成DependencyDescriptor
        DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
        desc.setContainingClass(bean.getClass());
        Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
        TypeConverter typeConverter = beanFactory.getTypeConverter();
        try {
            // 4.解析当前属性所匹配的bean实例,并把解析到的bean实例的beanName存储在autowiredBeanNames中
            value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
        } catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
        }
        synchronized (this) {
            if (!this.cached) {
                // 5.value不为空或者required为true
                if (value != null || this.required) {
                    // 6.如果属性依赖注入的bean不止一个(Array,Collection,Map),缓存cachedFieldValue放的是DependencyDescriptor
                    this.cachedFieldValue = desc;
                    // 7.注册依赖关系到缓存(beanName 依赖 autowiredBeanNames)
                    registerDependentBeans(beanName, autowiredBeanNames);
                    // 8.如果属性依赖注入的bean只有一个(正常都是一个)
                    if (autowiredBeanNames.size() == 1) {
                        String autowiredBeanName = autowiredBeanNames.iterator().next();
                        if (beanFactory.containsBean(autowiredBeanName)) {
                            // @Autowired标识属性类型和Bean的类型要匹配,因此Array,Collection,Map类型的属性不支持缓存属性Bean名称
                            // 9.检查autowiredBeanName对应的bean的类型是否为field的类型
                            if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                                // 10.将该属性解析到的bean的信息封装成ShortcutDependencyDescriptor,
                                // 以便之后可以通过getBean方法来快速拿到bean实例
                                this.cachedFieldValue = new ShortcutDependencyDescriptor(
                                        desc, autowiredBeanName, field.getType());
                            }
                        }
                    }
                } else {
                    this.cachedFieldValue = null;
                }
                // 11.缓存标识设为true
                this.cached = true;
            }
        }
    }
    if (value != null) {
        // 12.设置字段访问性
        ReflectionUtils.makeAccessible(field);
        // 13.通过反射为属性赋值,将解析出来的bean实例赋值给field
        field.set(bean, value);
    }
}

        到这里位置,我们就完成了bean的属性自动注入。

        

本文中的生命周期方法结合流程图展示如下:

举报

相关推荐

0 条评论