《深入浅出Spring》Spring上下文生命周期

本文详细介绍了Spring应用上下文的生命周期,包括14个阶段,如创建上下文、BeanFactory的创建与准备、初始化内建Bean等。文章强调了refresh方法的重要性,并解释了早期事件和事件监听器的概念。此外,还探讨了BeanFactoryPostProcessor和BeanPostProcessor的作用,以及在不同阶段如何处理bean的实例化和初始化。
摘要由CSDN通过智能技术生成

1、什么是spring应用上下文?

接口org.springframework.context.ApplicationContext表示spring上下文,下面2个实现类

org.springframework.context.support.ClassPathXmlApplicationContext
org.springframework.context.annotation.AnnotationConfigApplicationContext

2、应用上文生命周期(14个阶段)

1、创建spring应用上下文

2、上下文启动准备阶段

3、BeanFactory创建阶段

4、BeanFactory准备阶段

5、BeanFactory后置处理阶段

6、BeanFactory注册BeanPostProcessor阶段

7、初始化内建Bean:MessageSource

8、初始化内建Bean:Spring事件广播器

9、Spring应用上下文刷新阶段

10、Spring事件监听器注册阶段

11、单例bean实例化阶段

12、BeanFactory初始化完成阶段

13、Spring应用上下文启动完成阶段

14、Spring应用上下文关闭阶段

3、Spring应用上下文的使用

看下这段代码,是不是很熟悉,这就是spring上下文最常见的用法,稍后我们以这段代码为例,结合spring源码,来细说每个阶段的细节。

@Configuration
@ComponentScan
public class MainConfig {
   
    public static void main(String[] args) {
   
        //1.创建spring上下文
        AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext();
        //2.上下文中注册bean
        configApplicationContext.register(MainConfig.class);
        //3.刷新spring上下文,内部会启动spring上下文
        configApplicationContext.refresh();
        //4.关闭spring上下文
        System.out.println("stop ok!");
    }
}

4、阶段1:创建Spring应用上下文

对应这段代码

AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext();

看一下其类图,这里主要列出了AnnotationConfigApplicationContext2个父类

在这里插入图片描述

当调用子类的构造器的时候,默认会自动先调用父类的构造器,先来看一下GenericApplicationContext构造器源码,如下,将beanFactory创建好了。

public GenericApplicationContext() {
   
    this.beanFactory = new DefaultListableBeanFactory();
}

再来看看AnnotationConfigApplicationContext构造器源码,如下:

public AnnotationConfigApplicationContext() {
   
    //创建AnnotatedBeanDefinitionReader:用来读取及注册通过注解方式定义的bean
    this.reader = new AnnotatedBeanDefinitionReader(this); //@1
    //创建ClassPathBeanDefinitionScanner:bean定义扫描器,可以扫描包中的类,对满足条件的类,会将其注册到spring容器中
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

@1:new AnnotatedBeanDefinitionReader(this),进入这个方法内部,最终会走到下面这个方法,非常关键的一个方法,会向spring容器中注册5个关键的bean,这几个bean都是非常很重要的。

org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, @Nullable Object source) {
   
    //1、注册ConfigurationClassPostProcessor,这是个非常关键的类,实现了BeanDefinitionRegistryPostProcessor接口
    // ConfigurationClassPostProcessor这个类主要做的事情:负责所有bean的注册,如果想看bean注册源码的,可以在其postProcessBeanDefinitionRegistry方法中设置断点
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
   
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
    //2、注册AutowiredAnnotationBeanPostProcessor:负责处理@Autowire注解
    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
   
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
    //3、注册CommonAnnotationBeanPostProcessor:负责处理@Resource注解
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
   
        RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
    //4、注册EventListenerMethodProcessor:负责处理@EventListener标注的方法,即事件处理器
    if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
   
        RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
    }
    //5、注册DefaultEventListenerFactory:负责将@EventListener标注的方法包装为ApplicationListener对象
    if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
   
        RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
    }
    return beanDefs;
}

再来捋一下上面这段代码,主要向spring容器中注册了5个关键的bean

1、ConfigurationClassPostProcessor:这是个非常关键的类,建议去看一下他的源码,基本上我们自定义的bean都是通过这个类注册的,下面这些注解都是在这个类中处理的

@Configuration
@Component
@PropertySource
@PropertySources
@ComponentScan
@ComponentScans
@Import
@ImportResource
@Bean

2、AutowiredAnnotationBeanPostProcessor:负责处理@Autowire注解

3、注册CommonAnnotationBeanPostProcessor:负责处理@Resource注解

4、注册EventListenerMethodProcessor:负责处理@EventListener标注的方法,即事件处理器

5、注册DefaultEventListenerFactory:负责将@EventListener标注的方法包装为ApplicationListener对象

5、阶段2~阶段13
阶段2到阶段13,这中间的12个阶段都位于refresh方法中,所以refresh方法非常很重要,需要多花时间研究这个方法。

refresh方法源码如下:

org.springframework.context.support.AbstractApplicationContext#refresh
@Override
public void refresh() throws BeansException, IllegalStateException {
   
    // 阶段2:Spring应用上下文启动准备阶段
    prepareRefresh();
    // 阶段3:BeanFactory创建阶段
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    // 阶段4:BeanFactory准备阶段
    prepareBeanFactory(beanFactory);
    try {
   
        // 阶段5:BeanFactory后置处理阶段
        postProcessBeanFactory(beanFactory);
        // 阶段6:BeanFactory注册BeanPostProcessor阶段
        invokeBeanFactoryPostProcessors(beanFactory);
        // 阶段7:注册BeanPostProcessor
        registerBeanPostProcessors(beanFactory);
        
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值