spice and wolfspice and wolf Be the One you wanna Be

Bean的生命周期

生命周期及相关流程

  1. 准备阶段。围绕bean信息的加载器的创建、bean定义信息的存储、bean工厂的创建展开
    1. 首先需要加载不同的bean读取器为后面beanDefinition的读取做准备。bean的加载离不开三种方式:xml方式,读取并解析xml标签及属性来加载bean;注解方式,扫描指定文件夹及子目录中的文件,将被对应注解(@Component、@Controller、@Configuration、@Service、@Repository)标注的类作为bean加载;类全限定名直接导入;这几种方式的加载需要几个读取器和一个扫描器XmlBeanDefinitionReader、AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner
    2. 创建beanFactory。DefaultListableBeanFactory beanFactory = this.createBeanFactory();
    3. 加载beanDefinition。this.loadBeanDefinitions(beanFactory);
      1. 基于不同的实现类创建beanDefinitionReader并初始化
      2. 通过beanDefinitionReader加载beanDefinition。reader.loadBeanDefinitions(configResources);
        1. 创建BeanDefinition。AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition(parent, className, this.getBeanClassLoader());
        2. 加载beanDefinition。将对应的Class赋值给BeanDefinition的beanClass属性,并加载或初始化其他属性,例如懒加载标志位
        3. 注册beanDefinition。而后将beanName和beanDefinition通过键值对的方式保存到一个map中,并挂载到BeanDefinitionRegistry(实际上beanFactory就实现了BeanDefinitionRegistry,这里就是挂载到beanFactory上)的beanDefinitionMap属性上。this.getRegistry().registerBeanDefinition(beanName, bd);
      3. 将beanFactory挂载到上下文中。this.beanFactory = beanFactory;
  2. bean的生命周期。如果不能从缓存中取到bean的实例,则需要创建bean实例,通过调用链getBean->doGetBean->createBean->doCreateBean,来获取bean
    • 实例化。根据beanName从beanFactory的beanDefinitionMap中取出BeanDefinition,然后基于beanDefinition中的beanClass和其他属性进行反射创建。
    • 属性赋值。给bean的属性赋初始值,这一步会进行依赖注入,在此利用三级缓存解决了循环依赖问题。
    • 初始化。有四个扩展点
      • XXXAware
      • 初始化前
      • 初始化
      • 初始化后

准备阶段

从run方法开始

从run方法开始,逐步解析定位到bean生命周期逻辑。进入主启动类

这里主要用于启动spring的事件监听器,用于监听容器各个生命周期的各个事件,这个可以不管

        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.starting();

创建spring容器类

context = this.createApplicationContext();
加载不同的beanDefinitionReader

在上下文的准备阶段,对bean创建有主要影响的就是beanDefinitionLoader的加载

this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);

众所周知bean的加载方式离不开三种方式:

  • xml方式
  • 注解方式
  • 类限定名直接导入

基于这三种加载方式,需要各种不同的BeanDefinitionLoader,包括AnnotatedBeanDefinitionReader、XmlBeanDefinitionReader、ClassPathBeanDefinitionScanner,提前加载这些类为获取bean的class类做准备

到这上下文准备阶段(prepareContext)的bean加载准备就完成了

在refreshContext方法中同样需要为bean的创建做一些准备工作

this.refreshContext(context);

直接定位到里层的refresh()方法,它的三个实现类都会走AbstractApplicationContext中同步代码块的逻辑,这里面就包括了bean的生命周期的相关逻辑

创建beanFactory

在bean生命周期之前,需要提前创建beanFactory并初始化

其中在创建beanFacotry时会加载beanDefinition为后面bean的生命周期做准备:

ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();

继续在refreshBeanFactory中定位beanDefinitions的处理逻辑:

加载beanDefinition

loadBeanDefinitions()函数会基于对应的reader加载beanDefinition,这里我们看loadBeanDefinitions的其中一个实现类AbstractXmlApplicationContext中的loadBeanDefinitions

继续看更深的实现逻辑

这里看PropertiesBeanDefinitionReader的loadBeanDefinitions(Resource resource)的方法实现

继续往下,主要看看BeanDefinition的生成逻辑,这里props是一个bean name与类全限定名的map

最后定位到registerBeanDefinition方法

看到createBeanDefinition方法的处理逻辑

如果classLoader不为空,会给beanDefinition的BeanClass赋值对应的class,其实就是拿到beanDefinition的Class;如果为空则给BeanClassName赋值

而这里注册器的作用就是存放beanDefinition的map

看其中一个实现类的代码

registerBeanDefinition本身也只是在map中存储一个BeanName-BeanDefinition的键值对

beanDefinition处理完成后,就进入bean生命周期逻辑中了

然后继续向下定位bean的生命周期代码逻辑:

doGetBean中会调用createBean方法

createBean中又会调用doCreateBean,doCreateBean方法中包含了bean生命周期的几乎所有阶段

bean生命周期

    // AbstractBeanFactory.class
    
    protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
        String beanName = this.transformedBeanName(name);
        Object sharedInstance = this.getSingleton(beanName);
        Object bean;
        if (sharedInstance != null && args == null) {
            ...
            bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
        } else {
            ...

            try {
                RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
                ...

                // 判断是否是单例
                if (mbd.isSingleton()) {
                    // 获取单例
                    sharedInstance = this.getSingleton(beanName, () -> {
                        try {
                            return this.createBean(beanName, mbd, args);
                        } catch (BeansException var5) {
                            this.destroySingleton(beanName);
                            throw var5;
                        }
                    });
                    bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                } else if (mbd.isPrototype()) {
                    ...
                } else {
                    ...
                }
            } catch (BeansException var26) {
                this.cleanupAfterBeanCreationFailure(beanName);
                throw var26;
            }
        }

        if (requiredType != null && !requiredType.isInstance(bean)) {
            ...
        } else {
            return bean;
        }
    }

在这个方法中会根据三级缓存机制拿到缓存的bean,如果都没有则会执行bean的创建流程,即执行createBean()方法,createBean()的核心逻辑都在doCreateBean()方法中,所以我们想要了解bean的生命周期需要集中学习这个代码的执行逻辑。

    // AbstractAutowireCapableBeanFactory.class

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

        // 实例化
        if (instanceWrapper == null) {
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }

        Object bean = instanceWrapper.getWrappedInstance();
        ...

        // 判断是否是正在创建的单例Bean
        boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
        if (earlySingletonExposure) {
            ...

            // 添加到三级缓存
            this.addSingletonFactory(beanName, () -> {
                return this.getEarlyBeanReference(beanName, mbd, bean);
            });
        }

        Object exposedObject = bean;

        try {
            // 属性赋值
            this.populateBean(beanName, mbd, instanceWrapper);
            // 初始化
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);
        } catch (Throwable var18) {
            if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
                throw (BeanCreationException)var18;
            }

            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
        }

        ...
    }

bean的生命周期中的前三个阶段在doCreateBean()中都能定位到对应的方法:

  • 实例化(this.createBeanInstance(beanName, mbd, args))
  • 属性赋值(this.populateBean(beanName, mbd, instanceWrapper))
  • 初始化(this.initializeBean(beanName, exposedObject, mbd))
实例化
入参

传入的参数有三个,第一个beanName没什么好说的,第二个是beanDefinition,第三个是其他参数,这里我们往回追述一下beanDefinition是从哪里取的

这里首先会从AbstractBeanFactory类的mergedBeanDefinitons这个map中取

如果取不到则会返回this.getMergedBeanDefinition(beanName, this.getBeanDefinition(beanName))的返回值,其中this.getBeanDefinition(beanName)获取到的beanDefinition对象其实是从beanDefinitionMap中取的,这就跟之前beanDefinition的创建和注册对上了

当前类也的确是BeanDefinitionRegistry的实现类之一

然后getMergedBeanDefinition方法实现中返回的方法实例也是基于getBeanDefinition返回对象进行重载的

通过反射获取bean实例
                if (resolved) {
                    return autowireNecessary ? this.autowireConstructor(beanName, mbd, (Constructor[])null, (Object[])null) : this.instantiateBean(beanName, mbd);
                } else {
                    ...
                }

resolved标识位表示是否已经确定好beanDefinition的构造方法,如果为true,则判断autowireNecessary标志位,该标志位表示是否需要对构造方法进行参数的依赖注入,如果为true,反射的构造方法调用时会拿到构造方法依赖注入的入参;如果为false,则调用反射的构造函数并返回实例

属性赋值

属性赋值的参数有三:beanName、beanDefinition和instanceWrapper(刚创建的bean实例对象)

初始化
    // AbstractAutowireCapableBeanFactory.class

    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(() -> {
                this.invokeAwareMethods(beanName, bean);
                return null;
            }, this.getAccessControlContext());
        } else {
            this.invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        // 初始化前扩展
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
        }

        // 初始化
        try {
            this.invokeInitMethods(beanName, wrappedBean, mbd);
        } catch (Throwable var6) {
            throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
        }

        // 初始化后扩展
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

这里有四个扩展点:

  • xxxAware。
  • 初始化前。this.applyBeanPostProcessorsBeforeInitialization(bean, beanName)。
  • 初始化。afterPropertiesSet()。
  • 初始化后。this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)。会执行AOP动态代理操作并返回动态代理对象。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

Press ESC to close