SpringBoot源码初学者(三):配置bean的9种方式与BeanFactory的解析

ps:bean初始化相关的内容实在太多,不得已只好将其分成上下两篇来讲

  • 上篇 :主要讲解BeanFactory的相关内容,包括后置处理器的相关内容
  • 下篇 :主要讲解Bean的实例

一、啥子是Bean???

既然大家都是来看源码解析的,what is bean?这种问题显然有点小儿科的了,没有那个会告诉我意思是“小豆子”,那我就自问自答好了,springBean简单的概括:被Spring容器初始化、装配和管理的类,生命周期被spring支配。

1、bean的配置方式(熟悉的小伙伴可以直接跳过)

(1)xml配置

xml配置是早期的配置方式,SpringBoot出现后逐渐被淘汰,配置项复杂繁多,看起来杂乱无章,有些小伙伴入坑时间比较短,甚至没有接触过xml的配置,简单的演示一下,大家看个热闹。 创建bean之前先要有个类,SpringBoot还不能无中生有,不知道大家有没有女票了,没有的小伙伴今天有福气了,今天一人发一个!!!ohhhhhhhhhhhh!!!开搞使用SpringBoot new一个GirlFriend,定制女友贼刺激。

public class GirlFriend{
    private String name;
    private Integer age;
    private Integer height;
    private Integer weight;
    private List<String> hobby;
    
    public GirlFriend(){}
    
    public GirlFriend(String name,Integer age){
        this.name = name;
        this.age = age;
    }
    
    ....getSet省略....
}
复制代码

有了女朋友 还需要带回家,再定义一个Home

public class Home{
    private GirlFriend girlFriend;
    
    ....getSet省略....
}
复制代码

1)无参构造

在resources中创建一个xml文件,名字随意就好,叫first-love-girlfriend.xml好了

<?xml version="1.0" encoding="UTF-8">
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- 
        做笔记了!!
        上面那一大串子,主要功能是对当前的xml文档的格式做限制,什么节点可以出现什么节点不可以出现,这里只添加bean的校验
        xmlns:关于初始化bean的格式文件地址
        xmlns:xsi:辅助初始化bean
        xsi:schemaLocation:用于声明了目标名称空间的模式文档
-->
    <!-- 创建一个bean,id:唯一表示 ,class:全路径名-->
    <bean id="girlFriend" class="com.gyx.test.GirlFriend">
        <!-- 给属性赋值  name:属性名   value:注入的值 -->
        <property name="name" value="cuiHua"/>
        <!-- 男孩子都喜欢18岁的黄花大姑娘 -->
        <property name="age" value="18"/>
        <property name="hobby">
            <list>
                <value>看书</value>
                <value>吃零食</value>
            </list>
        </property>
    </bean>
    
    <bean id="home" class="com.gyx.test.Home">
        <!-- 使用ref来引用已经定义好的 bean对象 -->
        <property name="girlFriend" ref="girlFriend"/>
    </bean>
</beans>
复制代码

2)有参构造

...上面的重复略过....


<!-- 创建一个bean,id:唯一表示 ,class:全路径名-->
    <bean id="girlFriend" class="com.gyx.test.GirlFriend">
        <!-- 有参构造器注入,index:参数的位置从0开始,value:参数值 -->
        <construcort-arg index="0" value="cuiHua">
        <construcort-arg index="1" value="18">
        <property name="hobby">
            <list>
                <value>看书</value>
                <value>吃零食</value>
            </list>
        </property>
    </bean>
    
    
...下面的也重复略过....
复制代码

3)静态工厂方法

随着业务量的增长,为了解决广大男同胞的单身问题,手动创建已经无法满足需求,创建工厂批量生产

i. 定义抽象类

public abstract class GirlFriend{
    abstract String getName();
}
复制代码

ii. 实现抽象类

萝莉

public class Loli extends GirlFriend {
    @Override
    String  getName(){
        return name;
    }
}
复制代码

女王

public class Queen extends GirlFriend {
    @Override
    String  getName(){
        return name;
    }
}
复制代码

iii. 实现静态工厂

public class GirlFriendFactory {
    @Override
    public static GirlFriend  getGirlFriend(String type){
        if("queen".equals(type)){
            return new Queen();
        } else if("loli".equals(type)) {
            return new Loli();
        }else {
            return null;
        }
    }
}
复制代码

iv. xml配置

...上面的重复略过....


<!-- 创建一个bean,id:唯一表示 ,class:全路径名 ,factory-method:工厂方法   -->
    <bean id="loli" class="com.gyx.test.GirlFriendFactory" factory-method="getGirlFriend">
        <!-- 传入参数 -->
        <construcort-arg  value="queen">
    </bean>
    
    
...下面的也重复略过....
复制代码

4)实例工厂方法

i. 创建实例工厂

public class GirlFriendFactory {
    @Override
    public GirlFriend  getGirlFriend(String type){
        if("queen".equals(type)){
            return new Queen();
        } else if("loli".equals(type)) {
            return new Loli();
        }else {
            return null;
        }
    }
}
复制代码

ii. xml配置

...上面的重复略过....

<bean name="girlFriendFactory" class="com.gyx.test.GirlFriendFactory">
<!-- 创建一个bean,id:唯一表示 ,factory-bean:工厂bean ,factory-method:工厂方法   -->
<bean id="loli" factory-bean="girlFriendFactory" factory-method="getGirlFriend">
        <!-- 传入参数 -->
        <construcort-arg  value="loli">
</bean>

...下面的也重复略过....
复制代码

(2)java代码方式配置bean

1)@Component注解配置Bean(@Service、@Controller是一样的)

@Component
public class GirlFriend{
    private String name;
    private Integer age;
    private Integer height;
    private Integer weight;
    private List<String> hobby;
    
    public GirlFriend(){}
    
    public GirlFriend(String name,Integer age){
        this.name = name;
        this.age = age;
    }
    
    ....getSet省略....
}
复制代码

2)@Bean注解配置Bean

@Configuration
public class BeanConfiguration{
    @Bean
    public GirlFriend getGirlFriend(){
        return new GirlFriend("cuihua",18);
    }
}
复制代码

3)使用FactoryBean接口配置Bean

@Component
public class MyGirlFriend implements FactoryBean<GirlFriend>{
    @Override
    public GirlFriend getObject() throws Exception{
        return new Loli();
    }
}
复制代码

4)使用BeanDefinitionRegistryPostProcessor接口配置Bean

@Component
public class MyGirlFriend implements BeanDefinitionRegistryPostProcessor{
    //注册一个bean对象
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException{
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
        rootBeanDefinition.setBeanClass(Queen.class);
        registry.registerBeanDefinition("queen",rootBeanDefinition);
    }
    
    //这个方法可以向bean对象中注入值
    @Override
    public void postProcessBeanFactory(ConfiguraleListableBeanFactory beanFactory) throws BeansException{
        //获取到刚刚定义的 bean对象的定义
        BeanDefinition queen = beanFactory.getBeanDefinition("queen");
        //给对象添加属性值
        MutablePropertyValues propertyValues = queen.getPropertyValues();
        propertyValues.addPropertyValue("name","红太狼");
    }
}
复制代码

5)使用ImportBeanDefinitionRegistrar接口配置Bean

public  class MyGirlFriend implements ImportBeanDefinitionRegistrar{
     @Override
     public void registerBeanDefinition(AnnotationMetadata importingClassMetadata,BeanDefinitionRegistry registry){
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
        rootBeanDefinition.setBeanClass(Queen.class);
        registry.registerBeanDefinition("queen",rootBeanDefinition);
     }
}
复制代码

二、bean的创建过程

在前面的章节中,我们了解了9中创建bean的方式,那么SpringBoot到底是如何创建出这些GirlFriend的,“造人”???停停停,朗朗乾坤搞不得黄色。 创建bean、加载bean的过程,都是被封装在refresh方法中,我一般将这个方法称之为 “bean生命启点·spring启动关键·面试必问·refresh” ,之前对源码有所了解的小伙伴,肯定都听说过他的大名,不知道之前你们有没有完全弄懂这个方法,不过这都不要紧了!今天不要998,不要99.8!一篇文章直接带你一步到位,全面学懂refresh方法,话不多说!一起SpringBoot的内心深处吧!!

1、寻找refresh方法的位置

步骤1:照顾新朋友,我们还是从SpringBoot的启动类开始,一步步深入

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        //进入run方法
        SpringApplication.run(Application.class, args);
    }
}
复制代码

步骤2:ConfigurableApplicationContext类

public static ConfigurableApplicationContext run(Class<?> primarySource,
			String... args) {
       //还是进入run方法
		return run(new Class<?>[] { primarySource }, args);
}
复制代码

步骤3:再次进入run方法

public static ConfigurableApplicationContext run(Class<?>[] primarySources,
			String[] args) {
       //继续点击run方法
       //是不是有小伙伴开始疑惑了,这里为什么要点run,构造方法里面又做了什么事情
       //赶紧去补补这个系列的第一篇文章吧,答案就在里面
		return new SpringApplication(primarySources).run(args);
}
复制代码

步骤4:好啦!我们又来了SpringBoot的心脏方法,具体注释看这里 https://blog.csdn.net/qq_34886352/article/details/104949485

public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		configureHeadlessProperty();
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            //这个名字看上去和目标方法很像,点击进去看看
            //context是程序的上下文,配置的属性很多东西都在里面
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			listeners.started(context);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}
复制代码

步骤5: refresh方法就在这里

private void refreshContext(ConfigurableApplicationContext context) {
    //找到了!当当当!refresh方法就悄悄的躲在这里,毫不起眼,实际上暗藏杀机
    refresh(context);
    if (this.registerShutdownHook) {
        try {
            //这个方法会在jvm上注册一个钩子,当程序被关闭的时候,可以保证容器被正确的关闭掉
            context.registerShutdownHook();
        }
        catch (AccessControlException ex) {
            // Not allowed in some environments.
        }
    }
}
复制代码

2、refresh方法中的千回百转

步骤6:refresh方法的第一层

protected void refresh(ApplicationContext applicationContext) {
    //refresh方法不亏为军事要地!刚进来就碰上了守卫
    //判断传入的参数是否为AbstractApplicationContext的子类,如果不是直接异常
    Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
    //进行类型强转,多态的体现,继续点击refresh方法
    //这里会发现有3个实现,点AbstractApplicationContext类的
    ((AbstractApplicationContext) applicationContext).refresh();
}
复制代码

步骤7: 柳暗花明又一村,可以看出来refresh是一个boss级别的方法!不过大家别慌,方法虽多我们逐一击破

@Override
	public void refresh() throws BeansException, IllegalStateException {
        //这个方法是加的,在同一时间只需有一个线程执行当前方法
		synchronized (this.startupShutdownMonitor) {
			// 准备刷新!实际开工前的一些准备
          // 步骤8
			prepareRefresh();

			// 获取bean工厂
          // 步骤9
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 对beanFactory做一些配置
          //添加需要忽略的依赖、类加载器、后处理器、解析器等等,对了还有aop相关的后置处理器也是这里配置的
          // 步骤12
			prepareBeanFactory(beanFactory);

			try {
				// 在上下文中对BeanFactory进行一些后置的处理
                //默认情况下是一个空的实现,但是我们主要会以web服务运行运行,就会走到AnnotationConfigServletWebServerApplicationContext类中,别走错方法了
                // 主要是注册web请求相关的处理器、bean和配置
                // 步骤13
				postProcessBeanFactory(beanFactory);

                //实例化并调用bean工厂注册的后置处理器,这步操作必须在创建单例bean之前执行
                // 步骤15
				invokeBeanFactoryPostProcessors(beanFactory);

				//注册bean创建使用的后置处理器
              //步骤17
				registerBeanPostProcessors(beanFactory);

				// 初始化此上下文的消息源,国际化处理
                //messageSource是用来做国际化的
                    //判断BeanFactory是含有messageSource,如果没有就会创建一个
                    //步骤19
				initMessageSource();

				// 初始化事件广播器,spring监听器的一部分
                //步骤20
				initApplicationEventMulticaster();

				// 根据上下文环境初始化特定的bean
                //如果是web环境,将会进入到ServletWebServerApplicationContext的实现中
                //这个方法主要是创建一个web容器,例如SpringBoot内嵌的Tomcat容器
                //这里暂时跳过,在后续的更新中会进行详细的解析
				onRefresh();

				//注册监听器
                //向广播器中添加监听器的实现
                // 步骤21
				registerListeners();

				// 初始化单例bean
               //这里的内容放到下一篇文章中讲解,敬请期待
               //是非常重要的内容,也是面试中常问的内容
				finishBeanFactoryInitialization(beanFactory);

				// 清空缓存 并发送ContextRefreshedEvent事件
                //步骤22
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// 销毁已经创建的单例bean
				destroyBeans();

				// 改变 'active'属性的状态
				cancelRefresh(ex);

				// 抛出异常
				throw ex;
			}

			finally {
				// 删除掉所有的缓存,防止占用太大的内存,毕竟执行失败了,这些数据也没用了
				resetCommonCaches();
			}
		}
	}
复制代码

(1)前期准备

步骤8: 准备刷新!实际开工前的一些准备

//有些朋友版本可能和我不一样,进来之后发现并不是这些内容,不要紧点击同名方法就行了
protected void prepareRefresh() {
        //记录启动时间
		this.startupDate = System.currentTimeMillis();
        //修改上下文的状态,将状态切换到active,表示上下文要开始忙碌了,其他人不要来打扰他
		this.closed.set(false);
		this.active.set(true);
        //在debug模式下会打印一些,反正也不会去看的日志
		if (logger.isDebugEnabled()) {
			if (logger.isTraceEnabled()) {
				logger.trace("Refreshing " + this);
			}
			else {
				logger.debug("Refreshing " + getDisplayName());
			}
		}

		// Initialize any placeholder property sources in the context environment
        //对属性进行初始化
        //这里是2.1.0版本这个方法是空方法了,留下来做扩展的方法
		initPropertySources();

		// 关键属性的校验,如果必填的属性为空,就会抛出异常
		// 详情查看:ConfigurablePropertyResolver#setRequiredProperties
		getEnvironment().validateRequiredProperties();

		// 对earlyApplicationEvents进行初始化
       //SpringBoot监听器相关的内容,用来存放监听器的事件,到对应的位置,这些事件会被逐一触发
       //具体内容查看上期内容:https://blog.csdn.net/qq_34886352/article/details/105188150
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}
复制代码

prepareRefresh方法实际上和前台小妹的工作是一样的,工作安排如下:

  • 早上打卡上班,记录下上班时间,把手机静音,切换到active状态,准备开始一天的工作
  • 查看工作安排,由于调整,这段时间比较闲,所有的工作都丢给了别人
  • 点名,看看员工是否到齐,逐一确认必填属性是否为空
  • 拿出新的拜访登记册

这里教大家怎么使用关键属性的校验,怎么添加一个关键属性 其实也很简单,在第一节课中我们学习了ApplicationContextInitializer接口,其实添加关键属性就是他隐藏的小功能

public class TestInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        //从上下文中获取到程序环境
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        //设置一个关键属性,进行设置后需要在SpringBoot的配置文件Application中定义这个属性,否则就会抛出异常
        environment.setRequiredProperties("girlFriendName");
    }
}
复制代码

奇怪的知识增加了!

SpringBoot源码初学者(三):配置bean的9种方式与BeanFactory的解析

(2)BeanFactory的初始化

步骤9:获取bean工厂

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    //下面两个方法都是由GenericApplicationContext子类实现的,查看的时候记得是这个类
    //设置bean工厂的属性
    // 步骤10
    refreshBeanFactory();
    //获取bean工厂
    // 步骤11
    return getBeanFactory();
}
复制代码

这个方法比较简单,一共做了2件事情:

  • 设置beanFactory的序列化id
  • 获取beanFactory

步骤10:设置bean工厂属性

protected final void refreshBeanFactory() throws IllegalStateException {
    //将refreshed属性设置为true,表明已经开始刷新
    //使用CAS技术(compareAndSet),一种保证线程安全的防止无锁的机制,先比较再设置的方式,通过cpu底层完成的
    //先比较值是不是false,如果是就改成true
    if (!this.refreshed.compareAndSet(false, true)) {
        throw new IllegalStateException(
                "GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
    }
    //设置用于序列化的id,默认值为:application
    this.beanFactory.setSerializationId(getId());
}
复制代码

步骤11:获取bean工厂

public final ConfigurableListableBeanFactory getBeanFactory() {
    //这里方法很简单直接获取的GenericApplicationContext的属性,就是下面这个属性
    //属性的初始化是在构造方法中完成的,很简单无参构造方法new出来的
    //private final DefaultListableBeanFactory beanFactory;
    return this.beanFactory;
}
复制代码

步骤12: 对bean进行设置,中间涉及部分aop相关的内容

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 设置类加载器
    beanFactory.setBeanClassLoader(getClassLoader());
    // 设置表达式解析器  接配置文件中可能出现的SpEL表达式
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    //设置属性的编辑器,用来做属性转换、绑定的
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // 设置bean的后置处理器,这个是SpringBoot中一个比较重要的机制,后面会专门讲,当bean创建完成之后,会执行的回调方法
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    //设置自动装配需要忽略的接口,为什么忽略这些接口,我们放到和后置处理器一起讲
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

    // 给BeanFactory添加解析依赖,当beanFactory自身需要被解析、依赖的时候,可以指向自身
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    // 下面这三个也是一样的,当需要解析依赖的时候都指向自身
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // 在添加一个后置处理器,用于检测bean是否为监听器
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    //containsLocalBean方法会在bean的所有容器中判断,是否包含特定名称的bean
    //LOAD_TIME_WEAVER_BEAN_NAME:代码织入的功能,就是aop相关的内容了,以后也会陆续讲到的
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        //在添加一个后置处理器,用来处理代码织入的功能
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        // 添加一个零时的类加载器
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }

    // 注册一些默认的bean对象
    //运行环境的bean对象
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        //如果包含,那么就创建一个单例bean
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    //系统属性的bean对象
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    //系统运行环境的bean对象
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}
复制代码

总结一波,这个方法看似挺长的,实则很干燥:

  • 设置BeanFactory的一些属性
  • 添加了几个重要的后置处理器
  • 设置自动装配需要忽略的接口
  • 手动注册了一些默认的bean

步骤13:这个方法存在于AnnotationConfigServletWebServerApplicationContext类中,是子类的实现,看名字就知道是处理注解配置web服务的上下文类

@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    //看起来这个类还不是很“成熟”,有事直接找家长,go!去找他的监护人
    super.postProcessBeanFactory(beanFactory);
    //是否设置了基础包,就是扫描注解的范围
    if (this.basePackages != null && this.basePackages.length > 0) {
        this.scanner.scan(this.basePackages);
    }
    //这个也是一样的,判断是否设置需要扫描的带注解的类
    if (!this.annotatedClasses.isEmpty()) {
        this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
    }
}
复制代码

步骤14:此方法存在于ServletWebServerApplicationContext类中,也就是AnnotationConfigServletWebServerApplicationContext类的父类,不带有注解配置相关信息的上下文类

@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    //添加后置处理器,让web应用的bean可以获取(aware)到这个山下文
    beanFactory.addBeanPostProcessor(
            new WebApplicationContextServletContextAwareProcessor(this));
    //自动装配忽略ServletContextAware类型的对象
    beanFactory.ignoreDependencyInterface(ServletContextAware.class);
}
复制代码

(3)使用BeanFactory注册bean的定义

我们先要了解2个接口,这用有助于后续源码的阅读:

  • BeanDefinitionRegistryPostProcessor:bean定义注册器后置处理器,可以用于注册、删除bean的定义,同时还能修改bean的属性值 实现方法postProcessBeanDefinitionRegistry方法(注册bean定义)和postProcessBeanFactory方法(注入bean属性)
  • BeanFactoryPostProcessor:bean的后置处理器,能修改bean的属性值 实现方法postProcessBeanFactory方法(注入bean属性)

步骤15: 实例化并调用bean工厂注册的后置处理器,如果指定了顺序必须按顺序执行

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    //getBeanFactoryPostProcessors方法,会获取bean工厂的后置处理器,后置处理器是通过初始化和监听器实现的添加,具体的可以点方法,然后寻找到添加属性的方法,在看方法的调用位置
    //初始化注入的类叫做ConfigurationWarningsApplicationContextInitializer实现了ApplicationContextInitializer接口,是我们第一篇文章内容就讲到了,ApplicationContextInitializer接口的工作原理
    //监听器的类叫做ConfigFileApplicationListener,第二篇文章的内容,好好翻翻前面的文章吧
    
    //下面看一下invokeBeanFactoryPostProcessors方法,这个方法非常长,100多行,不过不要紧,原理很简单,我们一起看
    // 步骤16
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

    // 这里会检测是否有Aop的存在,如果有就会添加相关的后置处理器,用于后续的织入
    //这个就是后续Aop相关的内容了,这里不做讨论
    if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}
复制代码

步骤16: 调用bean工厂的后置处理器 参数说明: beanFactory:用来创建实例化bean的工厂对象 beanFactoryPostProcessors:当前这个工厂的后置处理器(对bean工厂进行加强)

public static void invokeBeanFactoryPostProcessors(
        ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

    //processedBeans中存放着需要优先处理的bean,实现了PriorityOrdered接口或者Ordered接口的对象,
    //防止这些对象被重复执行,客官往后看,后面解释
    Set<String> processedBeans = new HashSet<>();
    //判断beanFactory是否属于BeanDefinitionRegistry类型的
    //BeanDefinitionRegistry主要有一下几个功能
    //1.以key-value的形式注册bean,key为beanName,value为beanDefinition(bean的定义,含有bean几乎所有的信息)
    //2.根据beanName获取或者删除掉beanDefiniation
    //3.根据beanName判断beanDefinition是否存在
    if (beanFactory instanceof BeanDefinitionRegistry) {
        //进行类型转换
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        //处理会在这里被细分归类
        //regularPostProcessors用来存放普通的后置处理器
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
        //registryProcessors用来存放bean注册相关的处理器
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
        //循环后置处理器,并将它们归类
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            //判断是否为bean注册相关的后处理器的方法很简单
            //直接判断是否直接或间接的实现了BeanDefinitionRegistryPostProcessor接口
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                //将后置处理器进行类型转换
                BeanDefinitionRegistryPostProcessor registryProcessor =
                        (BeanDefinitionRegistryPostProcessor) postProcessor;
                //所有实现了BeanDefinitionRegistryPostProcessor接口的类,都需要实现postProcessBeanDefinitionRegistry这个方法
                //SpringBoot启动到这一步的时候,这些实现类便可以获取到bean定义的注册表
                //根据之前的注释可以知道BeanDefinitionRegistry有着所有bean的定义,那么就可以在这一步实现添加bean对象,删除bean对象的操作
                //这正是上文中“java代码方式配置bean”的第四种方法的原理
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                //归类到对应的集合中
                registryProcessors.add(registryProcessor);
            }
            else {
                //除了bean注册相关的后置处理器,就是普通的处理器,直接通过else分类就好了
                regularPostProcessors.add(postProcessor);
            }
        }

        //currentRegistryProcessors中按照优先级顺序存放  bean定义注册表的后置处理器
        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

        // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
        //从bean工厂根据类型获取bean的名称,三个参数分别的意思为
        //第一个参数:查询beanName使用的类型
        //第二个参数:true:从所有的bean中查找,false:从单例bean中查找
        //第三个参数:可以简单的理解是否使用缓存机制
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        //遍历获取到的bean定义注册表的后置处理器
        for (String ppName : postProcessorNames) {
            //判断当前后置处理器有没有实现PriorityOrdered接口,如果实现返回true
            //这里有必要说明一下  PriorityOrdered接口  和   Ordered接口
            //PriorityOrdered是Ordered的子类,两者都是用于设置调用的优先级,当是PriorityOrdered的优先度比Ordered优先度更高,永远先调用实现了PriorityOrdered的类
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                //将当前bean实例化,并且存放到currentRegistryProcessors中,getBean方法后面会详细说明
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                //将其添加到processedBeans中,优先处理他们
                processedBeans.add(ppName);
            }
        }
        //将currentRegistryProcessors根据优先级排序
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        //将这些bean定义注册表的后置处理器,添加到registryProcessors中(里面存放的是所有和bean注册相关的后置处理器)
        registryProcessors.addAll(currentRegistryProcessors);
        //这个方法会依次调用集合中对象的方法
        //忘记postProcessBeanDefinitionRegistry方法的小伙伴,全文搜索一下,上面有详细的解释
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        //最后清空掉集合中的内容
        currentRegistryProcessors.clear();

        // 再次获取一边Bean定义注册表后置处理器
        //不同的是上面处理的是实现了PriorityOrdered接口的对象,这里处理的是实现了Ordered接口的对象
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        //这里和上面一样,将PriorityOrdered接口和Ordered接口的实现做一个分离
        for (String ppName : postProcessorNames) {
            //注意!!这次获取的是实现了Ordered接口的对象
            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        //一样的排序
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        //一样的添加,registryProcessors集合中的对象是已经排序好的了
        registryProcessors.addAll(currentRegistryProcessors);
        //调用postProcessBeanDefinitionRegistry方法
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        //然后清空currentRegistryProcessors
        currentRegistryProcessors.clear();

        // 最后,有些BeanDefinitionRegistryPostProcessor可能没有实现PriorityOrdered接口或者Ordered接口
        //直接通过一个循环将这些对象调用了,不需要考虑执行顺序
        //当所有的BeanDefinitionRegistryPostProcessor执行完毕后,reiterate为false
        boolean reiterate = true;
        while (reiterate) {
            reiterate = false;
             // 再次获取一边Bean定义注册表后置处理器
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            //所有的都循环判断,然后执行
            for (String ppName : postProcessorNames) {
                //processedBeans方法最初创建的集合,用来排除之前执行过的BeanDefinitionRegistryPostProcessor对象
                if (!processedBeans.contains(ppName)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                    reiterate = true;
                }
            }
            //到这里又和上面是一样的了,就不多说了,这都是第三遍了
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();
        }

        // 好了!!到这里位置,所有的BeanDefinitionRegistryPostProcessor对象都被调用过了
        
        //上面处理的是BeanDefinitionRegistryPostProcessor接口的
        //下面这两句处理的是BeanFactoryPostProcessor接口
        //之前执行的实际上都是注册逻辑,真正的bean工厂的后置回调才刚刚开始
        //invokeBeanFactoryPostProcessors循环调用集合对象中的postProcessBeanFactory方法
        //registryProcessors和regularPostProcessors中的对象必然是实现了BeanFactoryPostProcessor接口的
        //必然会实现postProcessBeanFactory方法,跑就玩了
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    }

    else {
        //这个else是当bean工厂并非BeanDefinitionRegistry时进入的
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }

    // 这里会获取所有的bean工厂的后置处理器的beanName
    //为什么这里又获取一次?因为当执行BeanDefinitionRegistryPostProcessor的时候,是很有可能会注册一个普通的bean工厂的后置处理器进来的
    String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

    // 存放所有实现了PriorityOrdered接口的后置处理器
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
     // 存放所有实现了Ordered接口的后置处理器
    List<String> orderedPostProcessorNames = new ArrayList<>();
     // 存放两个接口都没有实现的的后置处理器
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    //对后置处理器进行分类
    for (String ppName : postProcessorNames) {
        if (processedBeans.contains(ppName)) {
            //processedBeans中存放的是已经执行过的后置处理器的BeanName,可以用来判断是否已经执行了
            //包含说明执行过,直接跳过
        }
        else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            //分离出实现了PriorityOrdered接口的对象,将其实例化,存放到对应集合中
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            //分离出实现了Ordered接口的对象,将BeanName存放到对应集合中
            orderedPostProcessorNames.add(ppName);
        }
        else {
            //剩下的自然是两个接口都没有实现的对象
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // 那么和之前一样!先排序
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    //然后按照顺序执行,不过这次执行是postProcessBeanFactory方法
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    // 接着轮到实现了Ordered接口的对象
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
    for (String postProcessorName : orderedPostProcessorNames) {
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    // 最后是两个接口都没实现的对象
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

    // 清空掉bean工厂中的元数据缓存,getBean方法会产生缓存
    beanFactory.clearMetadataCache();
}
复制代码

一起来总结一下,若此之长的方法不过是做了2件事情:

  • 调用BeanDefinitionRegistryPostProcessor的实现对象,往容器中添加新的bean定义
  • 调用BeanFactoryPostProcessor的实现对象,往这些bean定义中添加属性

(4)Bean的后置处理器

步骤17:注册bean的后置处理器

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    //PostProcessorRegistrationDelegate是用来专门处理后置处理器的工具类
    //调用注册方法  步骤18
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
复制代码

步骤18 :真正的开始注册bean的后置处理器 参数回顾! beanFactory:bean的工厂类,bean的容器 applicationContext:应用程序的上下文,包含程序的环境信息等等

public static void registerBeanPostProcessors(
        ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
    //获取bean工厂的后置处理器
    //别搞错了  之前获取的一直是BeanFactoryPostProcessor,现在要获取BeanPostProcessor
    //是从所有的beanDefinition(bean的定义)中获取bean的后置处理器
    //所以并不是之前用addBeanPostProcessor方法添加的后置处理器
    //另外使用getBeanNamesForType方法获取到的只是bean的名称 并不是实例对象
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

    //添加一个独特的后置处理器BeanPostProcessorChecker
    //BeanPostProcessorChecker是bean后置处理器的一个检测器
    //在某个bean实例化的过程中,所有的bean后置处理器都会被应用到这个bean上
    //这里说的“应用”,并不是一定要起到什么功能,后置处理器可能发现不是目标类型的bean便跳过了
    //但是如果这个后置处理器不能正确的运作在当前bean上,BeanPostProcessorChecker就会检测出来,并且做下标记
    //这里就是在计算bean的数量,是判断后置处理器的正确运转的条件之一
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    //将BeanPostProcessorChecker添加到后置处理器容器中
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

    // 存放实现了priorityOrdered接口(优先处理)的后置处理器
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    //存放MergedBeanDefinitionPostProcessor类型的后置处理器,特殊的后置处理器
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
    //存放实现了ordered接口的后置处理器的beanName
    List<String> orderedPostProcessorNames = new ArrayList<>();
    //存放没有实现ordered接口的后置处理器的beanName
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    //遍历所有的后置处理器
    for (String ppName : postProcessorNames) {
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            //实现了priorityOrdered接口(优先处理)的后置处理器,进入这里
            //处理器直接被实例化
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            //添加对应的容器中
            priorityOrderedPostProcessors.add(pp);
            //MergedBeanDefinitionPostProcessor是个特殊的处理器,他会将bean的定义进行合并
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                //添加对应的容器中
                internalPostProcessors.add(pp);
            }
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
         //实现了Ordered接口(优先处理)的后置处理器,进入这里
            orderedPostProcessorNames.add(ppName);
        }
        else {
            //没有实现Ordered接口和priorityOrdered接口的后置处理器
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // 对实现了priorityOrdered接口的后置处理器根据优先级进行排序
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    //注册后置处理器,循环的将priorityOrderedPostProcessors中的后置处理器添加到BeanFactory的后置处理器容器中
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

    // 接着对实现了Ordered接口的后置处理器,实例化,并且分离出MergedBeanDefinitionPostProcessor
    //存放实现了ordered接口的后置处理器的实例对象
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
    //循环之前保存的beanName
    for (String ppName : orderedPostProcessorNames) {
        //实例化后置处理器
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        //存放到容器中
        orderedPostProcessors.add(pp);
        //判断是否为MergedBeanDefinitionPostProcessor(用于合并bean定义的特殊后置处理器)类型的对象
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            //添加到对应容器中
            internalPostProcessors.add(pp);
        }
    }
    //排序
    sortPostProcessors(orderedPostProcessors, beanFactory);
    //将讲后置处理器注册到BeanFactory中
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);

    // 现在开始处理,没有实现ordered接口也没有实现priorityOrdered接口的后置处理器
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
    //再来一次基本套路
    for (String ppName : nonOrderedPostProcessorNames) {
        //实例化后置处理器
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        //存放到容器中
        nonOrderedPostProcessors.add(pp);
        //判断是否为MergedBeanDefinitionPostProcessor(用于合并bean定义的特殊后置处理器)类型的对象
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            //添加到对应容器中
            internalPostProcessors.add(pp);
        }
    }
    //不需要排序,直接将讲后置处理器注册到BeanFactory中
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

    // 最后处理MergedBeanDefinitionPostProcessor类型的后置处理器
    // 对MergedBeanDefinitionPostProcessor类型的后置处理器进行排序
    sortPostProcessors(internalPostProcessors, beanFactory);
    //将讲后置处理器注册到BeanFactory中
    registerBeanPostProcessors(beanFactory, internalPostProcessors);
    //这时候的后置处理器已经按照要求全部排序,并且进行实例化

    // 还需要在所有的后置处理器的后面添加一个用于发现bean是否为监听器的后置处理器
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
复制代码

(5)SpringBoot的一些扩展功能

步骤19:初始化此上下文的消息源,messageSource是用来做国际化的

protected void initMessageSource() {
    //获取到BeanFactory
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    //判断BeanFactory中是否存在MessageSource
    if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
        //实例化消息源的bean对象
        this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
        // 判断是否是个多层的消息源
        if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
            //进行强转,HierarchicalMessageSource为一个多层的消息源
            HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
            if (hms.getParentMessageSource() == null) {
                // 如果没有设定消息的父类,就获取父消息源,并赋值
                hms.setParentMessageSource(getInternalParentMessageSource());
            }
        }
        if (logger.isTraceEnabled()) {
            logger.trace("Using MessageSource [" + this.messageSource + "]");
        }
    }
    else {
        // DelegatingMessageSource基本上就是调用父级消息源的工具类,如果没有父级消息源,就什么都不会执行处理
        DelegatingMessageSource dms = new DelegatingMessageSource();
        //设置父级消息源
        dms.setParentMessageSource(getInternalParentMessageSource());
        //设置消息源
        this.messageSource = dms;
        //注册单例bean
        beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
        if (logger.isTraceEnabled()) {
            logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
        }
    }
}
复制代码

别看里面的对象名称非常晦涩难懂,其实只是做了一个国家化的初始化工作

步骤20:初始化广播器

protected void initApplicationEventMulticaster() {
    //获取BeanFactory
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    //判断是否包含广播器的bean
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        //实例化广播器,并赋值
        this.applicationEventMulticaster =
                beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
        if (logger.isTraceEnabled()) {
            logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
        }
    }
    else {
        //创建一个默认的广播器
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        //实例化,并赋值到BeanFactory中
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
        if (logger.isTraceEnabled()) {
            logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
                    "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
        }
    }
}
复制代码

步骤21:向广播器中添加监听器的实现

protected void registerListeners() {
    // 获取所有的监听器,并添加到广播器中
    //广播器的初始化在  步骤20 中
    //监听器的初始化和注册在上一篇文章中做个非常详细的说明,这里就不多说了
    for (ApplicationListener<?> listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener);
    }

    // 获取监听器类型的bean对象的beanName,但是这些对象不能在这里被实例化,因为我们需要让他们通过后置处理器进行处理
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        //添加到容器中缓存起来
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }

    // 这里有一个早期的广播器调用
    //由于spring的监听器机制在此之前并没有创建完成,但是有可能容器已经触发了某些事件,这些事件会被缓存在earlyApplicationEvents中
    //此刻监听器已经准备好了,可以执行之前缓存的事件了
    //获取早期的事件
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    //清空掉早期的事件
    this.earlyApplicationEvents = null;
    //执行刚刚获取的早期事件,一般情况下这里都是空的
    if (earlyEventsToProcess != null) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            //广播事件
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}
复制代码

步骤22:清空缓存 并发送ContextRefreshedEvent事件

protected void finishRefresh() {
    // 清楚上下文中的缓存
    clearResourceCaches();

    // 初始化生命周期处理组件
    initLifecycleProcessor();

    // 启动生命周期处理组件(生命周期组件,先不做讲解,其实蛮简单,小伙伴们有空可以自己先看看)
    getLifecycleProcessor().onRefresh();

    // 广播ContextRefreshedEvent事件
    publishEvent(new ContextRefreshedEvent(this));

    // bean的展示视图,这里不是重点,只能算是个附加的功能,暂时不讨论
    LiveBeansView.registerApplicationContext(this);
}
复制代码

原文 

https://juejin.im/post/5e95c720518825739a1b0754

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » SpringBoot源码初学者(三):配置bean的9种方式与BeanFactory的解析

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址