源码解析:Spring源码解析笔记启动过程(下)

Posted colodoo_纸伞

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了源码解析:Spring源码解析笔记启动过程(下)相关的知识,希望对你有一定的参考价值。

本文由colodoo(纸伞)整理
QQ 425343603
Java学习交流群(717726984)

当前Spring源码版本是 5.2.10.RELEASE

承接上一篇文章源码解析:Spring源码解析笔记(三)启动过程(中)。

上一篇文章,我们了解了我们定义的beanDefinition是怎么被实例化的,但还不是完全体,还不是我们平常用到的bean对象,我们继续阅读源码,看看bean是怎么属性填充并完成初始化的。

完成刷新(finishRefresh)

org.springframework.context.support.AbstractApplicationContext#finishRefresh
protected void finishRefresh() {
    // Clear context-level resource caches (such as ASM metadata from scanning).
    clearResourceCaches();

    // 为此上下文初始化生命周期处理器。
    initLifecycleProcessor();

    // 获取生命周期
       // 刷新生命周期
    // 首先将刷新传播到生命周期处理器.
    getLifecycleProcessor().onRefresh();

    // 发布最终活动.
    publishEvent(new ContextRefreshedEvent(this));

    // 参与 LiveBeansView MBean(如果活动).
    LiveBeansView.registerApplicationContext(this);
}

初始化生命周期处理器(initLifecycleProcessor)

org.springframework.context.support.AbstractApplicationContext#initLifecycleProcessor
protected void initLifecycleProcessor() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 获取生命周期处理器
    if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
        // 获取到这设置到当前对象lifecycleProcessor中
        this.lifecycleProcessor =
            beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
        if (logger.isTraceEnabled()) {
            logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
        }
    }
    else {
        // 初始化默认生命周期处理器
        DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
        // 为生命周期处理器设置bean工厂对象
        defaultProcessor.setBeanFactory(beanFactory);
        // 设置生命周期处理器
        this.lifecycleProcessor = defaultProcessor;
        // 注册生命周期处理器到bean工厂中
        beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
        if (logger.isTraceEnabled()) {
            logger.trace("No \'" + LIFECYCLE_PROCESSOR_BEAN_NAME + "\' bean, using " +
                         "[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
        }
    }
}

总结一下这段代码

  • 获取容器中存在的生命周期处理器,存在则设置,不存在则初始化。
  • 初始化默认生命周期处理器(DefaultLifecycleProcessor)
  • 默认生命周期处理器(defaultProcessor)注册到bean工厂(beanFactory)中。

这一步顾名思义就是把我们生命周期初始化需要用到的lifecycleProcessor准备好,接下来就要真正进入bean生命周期了。

生命周期刷新(onRefresh)

org.springframework.context.support.DefaultLifecycleProcessor#onRefresh
public void onRefresh() {
    startBeans(true);
    this.running = true;
}

进入到这个方法中发现具体实现逻辑在startBeans方法中,继续往下阅读。

启动 Beans(startBeans)

org.springframework.context.support.DefaultLifecycleProcessor#startBeans
private void startBeans(boolean autoStartupOnly) {
    // 获取生命周期Bean对象(多个)
    Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
    // 阶段
    Map<Integer, LifecycleGroup> phases = new HashMap<>();
    // 遍历所有生命周期对象
    lifecycleBeans.forEach((beanName, bean) -> {
        // 
        if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
            int phase = getPhase(bean);
            LifecycleGroup group = phases.get(phase);
            if (group == null) {
                group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
                phases.put(phase, group);
            }
            group.add(beanName, bean);
        }
    });
    if (!phases.isEmpty()) {
        List<Integer> keys = new ArrayList<>(phases.keySet());
        Collections.sort(keys);
        for (Integer key : keys) {
            phases.get(key).start();
        }
    }
}

总结下这部分代码:

  • 获取生命周期bean(getLifecycleBeans)
  • 同时进行生命周期bean实例化(getLifecycleBeans)

我们继续阅读getLifecycleBeans这个方法,看看有没有我们想要的东西。

获取生命周期 Bean(getLifecycleBeans)

org.springframework.context.support.DefaultLifecycleProcessor#getLifecycleBeans
protected Map<String, Lifecycle> getLifecycleBeans() {
    // 获取bean工厂对象
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 初始化beans
    Map<String, Lifecycle> beans = new LinkedHashMap<>();
    // 获取所有生命周期对象
    // 这里获取到的值是lifecycleProcessor
    String[] beanNames = beanFactory.getBeanNamesForType(Lifecycle.class, false, false);
    for (String beanName : beanNames) {
        // 获取用于注册的bean名称
        // 默认情况输出 -> lifecycleProcessor
        String beanNameToRegister = BeanFactoryUtils.transformedBeanName(beanName);
        // 判断是否为工厂bean
        // 这里默认情况输出 -> false
        boolean isFactoryBean = beanFactory.isFactoryBean(beanNameToRegister);
        // 如果为工厂bean则首字母加一个“&”符号
        // 这里不是工厂bean 输出 -> lifecycleProcessor
        String beanNameToCheck = (isFactoryBean ? BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
        // 判断是否存在该对象
        if ((beanFactory.containsSingleton(beanNameToRegister) &&
             (!isFactoryBean || matchesBeanType(Lifecycle.class, beanNameToCheck, beanFactory))) ||
            matchesBeanType(SmartLifecycle.class, beanNameToCheck, beanFactory)) {
            // 对该对象进行实例化
            Object bean = beanFactory.getBean(beanNameToCheck);
            if (bean != this && bean instanceof Lifecycle) {
                beans.put(beanNameToRegister, (Lifecycle) bean);
            }
        }
    }
    // 返回实例化后的生命周期对象
    return beans;
}

这一步很明显,前面都是对生命周期对象的bean名称进行获取。

看到我们很熟悉的beanFactory.getBean,说明它又帮生命周期bean进行了实例化,最后返回实例化后的生命周期对象。

beanFactory.getBean 这部分的源码,可以阅读上一篇文章 源码解析:Spring源码解析笔记(三)启动过程(中)

阅读到这里,我们没有发现属性注入的地方,反过头来看看是不是知道遗漏了哪些地方。

经过我的调试,发现需要改造一下我们的代码,因为我发现我们的代码并没有存在依赖关系,我们的userService并没有依赖任何的其他bean。

我们新建一个userController去调用它,并且依赖userService这个bean。

改造代码

UserController

package com.zhisan.spring.controller;

import com.zhisan.spring.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

public class UserController {

    private UserService userService;

    public void login() {
        userService.login();
    }

    public UserService getUserService() {
        return userService;
    }

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

MainXml.java

package com.zhisan.spring;

import com.zhisan.spring.config.Config;
import com.zhisan.spring.controller.UserController;
import com.zhisan.spring.service.UserService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainXml {

    public static void main(String[] args) {

        // XML方式
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");

        UserController userController = applicationContext.getBean("userController", UserController.class);
        userController.login();

    }
}

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:task="http://www.springframework.org/schema/task" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:cache="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="
          http://www.springframework.org/schema/beans 
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="userController" class="com.zhisan.spring.controller.UserController">
        <property name="userService" ref="userService"></property>
    </bean>
    <bean id="userService" class="com.zhisan.spring.service.UserService"> </bean>

</beans>

改造完后,我们继续调试。

在下面这populateBean方法上打上断点,方便调试。

因为寻找入口的过程比较漫长,所以中间的篇幅就省略了。

填充 Bean(populateBean)

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { 
   
    // 这里省略了一些无关的逻辑代码...

    // 这里会把类中的属性值都获取到
    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

    // 省略一些校验代码...

    // 判断属性值列表是否为空,不空则进入属性应用
    if (pvs != null) {
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

这部分的代码主要是完成属性填充的一些获取和校验,真正的填充属性值逻辑在applyPropertyValues,我们继续阅读这个方法。

应用属性值(applyPropertyValues)

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyPropertyValues
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
    // 判断是否为空
    if (pvs.isEmpty()) {
        return;
    }

    // 校验环境
    if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
        ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
    }

    // 变量准备
    MutablePropertyValues mpvs = null;
    List<PropertyValue> original;

    // 判断类型
    if (pvs instanceof MutablePropertyValues) {
        mpvs = (MutablePropertyValues) pvs;
        // 判断是否已经转换
        if (mpvs.isConverted()) {
            // Shortcut: use the pre-converted values as-is.
            try {
                bw.setPropertyValues(mpvs);
                return;
            }
            catch (BeansException ex) {
                throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Error setting property values", ex);
            }
        }
        // 获取属性值列表
        // result = {ArrayList@1625}  size = 1
        // 0 = {PropertyValue@1990} "bean property \'userService\'"
        //  name = "userService"
        //  value = {RuntimeBeanReference@2000} "<userService>"
        //  optional = false
        //  converted = false
        //  convertedValue = null
        //  conversionNecessary = null
        //  resolvedTokens = null
        //  source = null
        //  attributes = {LinkedHashMap@2001}  size = 0
        original = mpvs.getPropertyValueList();
    }
    else {
        original = Arrays.asList(pvs.getPropertyValues());
    }

    TypeConverter converter = getCustomTypeConverter();
    if (converter == null) {
        converter = bw;
    }
    BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

    // Create a deep copy, resolving any references for values.
    List<PropertyValue> deepCopy = new ArrayList<>(original.size());
    boolean resolveNecessary = false;
    for (PropertyValue pv : original) {
        if (pv.isConverted()) {
            deepCopy.add(pv);
        }
        else {
            String propertyName = pv.getName();
            Object originalValue = pv.getValue();
            if (originalValue == AutowiredPropertyMarker.INSTANCE) {
                Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
                if (writeMethod == null) {
                    throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
                }
                originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
            }
            // 属性值实例化
            Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
            Object convertedValue = resolvedValue;
            boolean convertible = bw.isWritableProperty(propertyName) &&
                !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
            if (convertible) {
                convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
            }
            if (resolvedValue == originalValue) {
                if (convertible) {
                    pv.setConvertedValue(convertedValue);
                }
                deepCopy.add(pv);
            }
            else if (convertible && originalValue instanceof TypedStringValue &&
                     !((TypedStringValue) originalValue).isDynamic() &&
                     !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
                pv.setConvertedValue(convertedValue);
                deepCopy.add(pv);
            }
            else {
                resolveNecessary = true;
                deepCopy.add(new PropertyValue(pv, convertedValue));
            }
        }
    }
    if (mpvs != null && !resolveNecessary) {
        mpvs.setConverted();
    }
    
    // 中间没有中文注释的部分可以忽略...不是主要逻辑

    try {
        // 设置属性值
        bw.setPropertyValues(new MutablePropertyValues(deepCopy));
    }
    catch (BeansException ex) {
        throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Error setting property values", ex);
    }
}

这部分做了如下几件事:

  • 遍历了所有的属性值(for)
  • 实例化属性值所需的bean并获取(resolveValueIfNecessary)
  • 转换属性(convertForProperty)
  • 填充属性(setPropertyValues)

设置属性(setValue)

org.springframework.beans.BeanWrapperImpl.BeanPropertyHandler#setValue
public void setValue(@Nullable Object value) throws Exception {
    // 通过反射获取到setter方法的对象
    // 这里输出:public void com.zhisan.spring.controller.UserController.setUserService(com.zhisan.spring.service.UserService)
    Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
                          ((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
                          this.pd.getWriteMethod());
    // 设置可访问
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            ReflectionUtils.makeAccessible(writeMethod);
            return null;
        });
        try {
            AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
                                          () -> writeMethod.invoke(getWrappedInstance(), value), acc);
        }
        catch (PrivilegedActionException ex) {
            throw ex.getException();
        }
    }
    else {
        // 设置可访问方法
        ReflectionUtils.makeAccessible(writeMethod);
        // 执行方法
        // value=userService对象
        writeMethod.invoke(getWrappedInstance(), value);
    }
}

这里是真正填充属性的逻辑方法,原理也是基于反射。

  • 通过反射获取到setter方法
  • 通过执行setter方法把处理后的参数设置到属性中。

至此,完成是填充属性这个步骤,接下来就是要完成bean生命周期中的最后一步,完成初始化。

初始化Bean(initializeBean)

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    }
    else {
        // 调用Aware方法
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null),
            beanName, "Invocation of init method failed", ex);
    }
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
    }

这里除了调用invokeInitMethods这个方法是主要逻辑,其他部分暂时可以忽略,继续阅读invokeInitMethods方法。

调用设置方法(invokeInitMethods)

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
    throws Throwable {

    // 是否初始化bean
    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isTraceEnabled()) {
            logger.trace("Invoking afterPropertiesSet() on bean with name \'" + beanName + "\'");
        }
        if (System.getSecurityManager() != null) {
            try {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                    ((InitializingBean) bean).afterPropertiesSet();
                    return null;
                }, getAccessControlContext());
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }
        else {
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }

    if (mbd != null && bean.getClass() != NullBean.class) {
        String initMethodName = mbd.getInitMethodName();
        if (StringUtils.hasLength(initMethodName) &&
            !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
            !mbd.isExternallyManagedInitMethod(initMethodName)) {
            // 调用自定义初始化方法
            // 判断该bean上是否含有初始化方法
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

这个部分最主要的逻辑就是判断对象是否,需要执行初始化方法,具体逻辑在invokeCustomInitMethod这个方法中。

调用自定义初始化方法(invokeCustomInitMethod)

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeCustomInitMethod
  • 获取bean定义(beanDefinition)中的初始化方法。
  • 通过反射获取初始化方法
  • 执行初始化方法

这是这个方法的逻辑,就不详细解析源码了。

最后

至此,完成bean生命周期的所有过程,启动过程篇幅结束!

接下来的文章我们会继续研究这些接口相关的设计。

以上是关于源码解析:Spring源码解析笔记启动过程(下)的主要内容,如果未能解决你的问题,请参考以下文章

Spring源码解读---启动过程源码解析

Spring源码解读---启动过程源码解析

Spring源码解读---启动过程源码解析

Spring源码解读---启动过程源码解析

dubbo系列dubbo启动过程源码解析

携程Apollo client Spring整合启动过程源码追踪