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

Posted *King*

tags:

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

Spring源码解读(8)—启动过程源码解析

Spring启动

Spring启动就是构造ApplicationContext对象及调用refresh方法的过程

Spring启动主要做了以下几件事情:

  1. 构造一个BeanFactory对象
  2. 解析配置类,得到BeanDefinition,并注册到BeanFactory中
    • 解析@CompanentScan注解,此时会完成扫描
    • 解析@Import注解
    • 解析@Bean注解。。。
  3. 因为ApplicationContext还支持国持化,所以还需初始化MessageSource对象
  4. ApplicationContext还支持事件机制,所以还需初始化ApplicationEventMulticaster对象
  5. 把用户定义的ApplicationListener对象添加到ApplicationContext中,等Spring启动完了就要发布事件了
  6. 创建非懒加载的单例Bean对象,并存在BeanFactory的单例池中
  7. 调用Lifecycle Bean的start()方法
  8. 发布ContextRefreshEvent事件

由于Spring启动过程中需要创建非懒加载的单例Bean对象,那么就需要用到PostProcessor,所以Spring在启动过程中需要做以下两件事:

  1. 生成默认的BeanPostProcessor对象,并添加到BeanFactory中
    • AutowiredAnnotationBeanPostProcessor:处理@Autowired、@Value
    • CommonAnnotationBeanPostProcessor:处理@Resource、@PostConstruct、@PreDestroy
    • ApplicationContextAwareProcessor:处理ApplicationContextAware等回调
  2. 找到外部用户所定义的BeanPostProcessor对象(类型为BeanPostProcessor的Bean对象),并添加到BeanFactory中

BeanFactoryPostProcessor

BeanPostProcessor表示Bean的后置处理器,是用来对Bean进行加工的,类似的BeanFactoryPostProcessor为BeanFactory的后置处理器,用来对BeanFactory进行加工的。

Spring支持用户定义BeanFactoryPostProcessor的实现类Bean,来对BeanFactory进行加工

public class KingBeanFactoryPostProcessor implements BeanFactoryPostProcessor 
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException 
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");
        beanDefinition.setAutowireCandidate(false);
    

以上代码就是利用BeanFactoryPostProcessor来拿到BeanFactory,然后获取BeanFactory内的某个BeanDefinition对象并进行修改,这一步是发生在Spring启动时,创建单例Bean之前的,所以此时对BeanDefiniton修改是会生效的。

注意:在ApplicationContext内部有一个核心的DefaultListableBeanFactory,它实现了ConfigurableListableBeanFactory和BeanDefinitionRegistry接口,所以ApplicationContext和DefaultListableBeanFactory是可以注册BeanDefinition的,但是ConfigurableListableBeanFactory是不能注册BeanDefinition的,只能获取BeanDefinition,然后做修改。

所以Spring还提供了一个BeanFactoryPostProcessor的子接口:BeanDefinitionRegistryPostProcessor

BeanDefinitionRegistryPostProcessor


BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor接口,并新增了一个方法,方法参数为BeanDefinitionRegistry,如果换们提供一个类来实现BeanDefinitionRegistryPostProcessor,那么在postProcessBeanDefinitionRegistry()方法中就可以注册BeanDefinition了。

public class KingBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor 
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException 
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
        beanDefinition.setBeanClass(User.class);
        registry.registerBeanDefinition("user", beanDefinition);
    

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException 
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService"); 
        beanDefinition.setAutowireCandidate(false);
    

理解refresh()


这是ConfigurableApplicationContext接口上的refresh()方法的注解,意思是:加载或刷新持久化的配置,可能是xml文件,属性文件或关系数据库中存储的。由于这是一个启动方法,如果失败,它应该销毁已经创建的单例,以避免占用资源。也就是说在调用该方法之后,应该实例化所有的单例,或者根本不实例化单例。

在Spring设计中,也提供可以刷新的ApplicationContext和不可以刷新的ApplicationContext

// 可以刷新的ApplicationContext
AbstractRefreshableApplicationContext extends AbstractApplicationContext

//不可以刷新的ApplicationContext
GenericApplicationContext extends AbstractApplicationContext

AnnotationConfigApplicationContext继承的是GenericApplicationContext,所以它是不能刷新的。

AnnotationConfigWebApplicationContext继承的是AbstractRefreshableWebApplicationContext,所以它是可以刷新的

refresh()底层原理流程


以AnnotationConfigApplicationContext为例,来看看refresh的底层原理:

  1. 在调用AnnotationConfigApplicationContext的构造方法之前,会调用父类GenericApplicationContext的无参构造方法,会构造一个BeanFactory,为DefaultListableBeanFactory
  2. 构造AnnotatedBeanDefinitionReader(增加一些基础的的PostProcessor),同时对BeanFactory进行设置和添加PostProcessor(后置处理器)
  3. 构造ClassPathBeanDefinitionScanner(主要是用来扫描得到注册BeanDefinition)
  4. 利用reader注册AppConfig为BeanDefinition,类型为AnnotatedGenericBeanDefinition
  5. 调用refresh方法
  6. prepareRefresh():记录启动时间,可以允许子容器设置一些内容到Environment中,验证Environment中是否包括了必须要有的属性
  7. obtainFreshBeanFactory():进行BeanFactory的refresh,在这里会去调用子类的refreshBeanFactory方法,具体子类是怎么刷新的得看子类,然后再调用子类的getBeanFactory方法,重新得到一个BeanFactory
  8. prepareBeanFactory(beanFactory):设置beanFactory的类加载器,设置表达式解析器,添加PropertyEditorRegistrar,添加一个Bean的后置处理器,添加ignoredDependencyInterface,添加resolvableDependencies,添加一个Bean的后置处理器ApplicationListenerDetector,增加一个Bean的后置处理器LoadTimeWeaverAwareProcessor,增加一些单例bean到单例池
  9. postProcessBeanFactory(beanFactory) : 提供给AbstractApplicationContext的子类进行扩展
  10. invokeBeanFactoryPostProcessors(beanFactory):执行BeanFactoryPostProcessor
  11. 得到BeanDefinition并注册到BeanFactory中
  12. registerBeanPostProcessors(beanFactory):这一步会把BeanFactory中所有的BeanPostProcessor找出来并实例化得到一个对象,并添加到BeanFactory中去(属性 beanPostProcessors),最后再重新添加一个ApplicationListenerDetector对象(之前其实 就添加了过,这里是为了把ApplicationListenerDetector移动到最后)
  13. initMessageSource():如果BeanFactory中存在一个叫做"messageSource"的 BeanDefinition,那么就会把这个Bean对象创建出来并赋值给ApplicationContext的messageSource属性,让ApplicationContext拥有国际化的功能
  14. initApplicationEventMulticaster():如果BeanFactory中存在一个叫做"applicationEventMulticaster"的BeanDefinition,那么就会把这个Bean对象创建出来并赋值给ApplicationContext的applicationEventMulticaster属性,让ApplicationContext拥有事件发布的功能
  15. onRefresh():提供给AbstractApplicationContext的子类进行扩展
  16. registerListeners():从BeanFactory中获取ApplicationListener类型的beanName,然后添加到ApplicationContext中的事件广播器applicationEventMulticaster中去,到这一步因为FactoryBean还没有调用getObject()方法生成Bean对象,所以这里要在根据类型找一下ApplicationListener,记录一下对应的beanName
  17. finishBeanFactoryInitialization(beanFactory):完成BeanFactory的初始化,主要就是实例化非懒加载的单例Bean
  18. finishRefresh():BeanFactory的初始化完后,就到了Spring启动的最后一步了
  19. 设置ApplicationContext的lifecycleProcessor,默认情况下设置的是DefaultLifecycleProcessor
  20. 调用lifecycleProcessor的onRefresh()方法,如果是DefaultLifecycleProcessor,那么会获取所有类型为Lifecycle的Bean对象,然后调用它的start()方法,这就是ApplicationContext的生命周期扩展机制
  21. 发布ContextRefreshedEvent事件

执行BeanFactoryPostProcessor

  1. 执行通过ApplicationContext添加进来的BeanDefinitionRegistryPostProcessor的 postProcessBeanDefinitionRegistry()方法

  2. 执行BeanFactory中实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor的 postProcessBeanDefinitionRegistry()方法

  3. 执行BeanFactory中实现了Ordered接口的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法

  4. 执行BeanFactory中其他的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法

  5. 执行上面所有的BeanDefinitionRegistryPostProcessor的postProcessBeanFactory()方法

  6. 执行通过ApplicationContext添加进来的BeanFactoryPostProcessor的postProcessBeanFactory()方法

  7. 执行BeanFactory中实现了PriorityOrdered接口的BeanFactoryPostProcessor的postProcessBeanFactory()方法

  8. 执行BeanFactory中实现了Ordered接口的BeanFactoryPostProcessor的postProcessBeanFactory()方法

  9. 执行BeanFactory中其他的BeanFactoryPostProcessor的postProcessBeanFactory()方法

Lifecycle的使用

Lifecycle表示的是ApplicationContext的生命周期,可以定义一个SmartLifecycle来监听ApplicationContext的启动和关闭:

import org.springframework.context.SmartLifecycle;
import org.springframework.stereotype.Component;

@Component
public class KingLifecycle implements SmartLifecycle 
    private boolean isRunning = false;
    @Override
    public void start() 
        System.out.println("启动");
        isRunning = true;
    

    @Override
    public void stop() 
        //要触发stop(),要调用context.close(),或注册关闭钩子(context.registerShutdownHook();)
        System.out.println("停止");
        isRunning = false;
    

    @Override
    public boolean isRunning() 
        return isRunning;
    

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

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

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

Spring源码解读---Bean生命周期源码解析

Spring源码解读---Bean生命周期源码解析

Spring源码解读---解析配置类

Spring源码解读---解析配置类