《Spring系列》第5章 refresh()

前言

Spring框架中最重要的肯定是IOC容器,那么其如何进行初始化,就是通过refresh()这个方法,无论是单独使用Spring框架,还是SpringBoot,最终都会通过执行到这个方法,那么下面会介绍一下这个方法

一、IOC容器初始化过程

对于单独测试Spirng框架的场景,有两个常见的高级容器 AnnotationConfigApplicationContextClassPathXmlApplicationContext,在这两个类的构造方法,都会使用到refresh()来刷新容器

AnnotationConfigApplicationContext

AnnotationConfigApplicationContext会通过扫描配置类来创建IOC容器

    @Test
    public void m1() {
       AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AspectConfig.class);
       MathCalculator mathCalculator = context.getBean(MathCalculator.class);
       int ans = mathCalculator.div(10, 5);
       System.out.println("结果:" + ans);
    }

	public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
        // 调用无参构造方法
		this();
        // 注册新的组件
		register(componentClasses);
        // 刷新容器
		refresh();
	}

构造方法

public AnnotationConfigApplicationContext() {
   StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
   // 创建注解Reader
   this.reader = new AnnotatedBeanDefinitionReader(this);
   createAnnotatedBeanDefReader.end();
   // 创建类扫描
   this.scanner = new ClassPathBeanDefinitionScanner(this);
}

创建的AnnotatedBeanDefinitionReader

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
   this(registry, getOrCreateEnvironment(registry));
}

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
   Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
   Assert.notNull(environment, "Environment must not be null");
   this.registry = registry;
   this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
   // 这里最后一行很关键,注册了一些核心的BeanPostProcessor
   AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

下面的方法就是容器启动时初始化,注册一些基础使用的类,其中有一个需要着重看一眼的就是负责处理@Configuration的后置处理器ConfigurationClassPostProcessor

public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
   registerAnnotationConfigProcessors(registry, null);
}

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
      BeanDefinitionRegistry registry, @Nullable Object source) {

   DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
   if (beanFactory != null) {
      if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
         beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
      }
      if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
         beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
      }
   }

   Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
	
   // 这里是最重要的,就是注册用来处理@Configuration注解的后置处理器
   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));
   }

   // 省略了一些代码

   return beanDefs;
}

ClassPathXmlApplicationContext

加载bean的xml文件,底层也是通过refresh()方式

public ClassPathXmlApplicationContext(
      String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
      throws BeansException {

   super(parent);
   setConfigLocations(configLocations);
   if (refresh) {
      refresh();
   }
}

二、refresh()

方法简介

refresh()ConfigurableApplicationContext中的接口,子类AbstractApplicationContext重写了该方法,负责初始化IOC容器
在这里插入图片描述

该方法中总共包含12个方法,大体的工作内容介绍:

  1. 刷新前的准备工作
  2. 获取Bean工厂
  3. 工厂前期的准备
  4. 子类重写方法,可以对Bean工厂进行扩展
  5. 执行BeanFactory的后置处理器
  6. 注册Bean的后置处理器
  7. 初始化消息源,负责国际化
  8. 初始化上下文事件
  9. 子类重写方法,初始化其它特殊bean
  10. 注册监听器
  11. 工厂基本创建完毕,剩余的收尾工作
  12. 刷新完成,剩余的收尾工作
	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

			// Prepare this context for refreshing. 
             // <1> 准备预处理:记录容器的启动时间startupDate, 标记容器为激活,初始化上下文环境如文件路径信息,验证必填属性是否填写
			prepareRefresh();

			// <2> 告诉子类去刷新bean工厂,此方法解析配置文件并将bean信息存储到beanDefinition中,注册到BeanFactory
             //(但是未被初始化,仅将信息写到了beanDefination的map中)**重点方法,下面的操作都基于这个beanFactory进行的
             ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			// <3> 设置beanFactory的基本属性:类加载器,添加多个beanPostProcesser
             prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
                 // <4> 扩展机制: 允许上下文子类中对bean工厂进行后处理
				postProcessBeanFactory(beanFactory);
				
				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
                  /**************************以上是BeanFactory的创建及预准备工作  ****************/
				// Invoke factory processors registered as beans in the context.
                 // <5> 调用BeanFactoryPostProcessor各个实现类的方法 
				invokeBeanFactoryPostProcessors(beanFactory);

                 // <6> 注册 BeanPostProcessor 的实现类
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();

                  // <7> 初始化ApplicationContext的MessageSource组件(资源文件),如国际化文件,消息解析,绑定等
				initMessageSource();

                  // <8> 初始化ApplicationContext事件广播器
				initApplicationEventMulticaster();

				// <9> 在特定上下文子类中初始化其他特殊bean
				onRefresh();

				// <10> 获取所有的事件监听器,并将监听器注册到事件广播器
				registerListeners();

				// <11> 初始化所有不是懒加载的singleton bean
				finishBeanFactoryInitialization(beanFactory);

				// <12> 广播事件:ApplicationContext初始化完成
				finishRefresh();
			}

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

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
                 // 重置 Spring 核心中的公共自省缓存,因为我们可能不再需要单例 bean 的元数据......
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
				contextRefresh.end();
			}
		}
	}

<1> prepareRefresh() 刷新准备

1、prepareRefresh()刷新前的预处理;
	1)、initPropertySources()初始化一些属性设置;子类自定义个性化的属性设置方法;
	2)、getEnvironment().validateRequiredProperties();检验属性的合法等
	3)、earlyApplicationEvents= new LinkedHashSet<>();保存容器中的一些早期的事件;
	/**
	 * Prepare this context for refreshing, setting its startup date and  容器刷新的准备工作,设置启动时间
	 * active flag as well as performing any initialization of property sources. 以及初始化属性源
	 */
	protected void prepareRefresh() {
		// Switch to active.
		this.startupDate = System.currentTimeMillis(); // 获取当前时间
         // 设置关闭状态false 启动状态true
		this.closed.set(false);
		this.active.set(true);

         // 输出日志
		if (logger.isDebugEnabled()) {
			if (logger.isTraceEnabled()) {
				logger.trace("Refreshing " + this);
			}
			else {
				logger.debug("Refreshing " + getDisplayName());
			}
		}

		// Initialize any placeholder property sources in the context environment.
         // 初始化一些属性在容器环境中 留给子类重写
		initPropertySources();

		// Validate that all properties marked as required are resolvable:
		// see ConfigurablePropertyResolver#setRequiredProperties
         // 验证属性的是否合法
		getEnvironment().validateRequiredProperties();

		// Store pre-refresh ApplicationListeners...
		if (this.earlyApplicationListeners == null) {
			this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
		}
		else {
			// Reset local application listeners to pre-refresh state.
			this.applicationListeners.clear();
			this.applicationListeners.addAll(this.earlyApplicationListeners);
		}

		// Allow for the collection of early ApplicationEvents,
		// to be published once the multicaster is available...
         // 通过集合保存早期的容器事件
         // 等派发起好了以后,在派发出去
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}

a> initPropertySources()

是个空方法,留给子类重写自定义

	/**
	 * <p>Replace any stub property sources with actual instances.
	 * @see org.springframework.core.env.PropertySource.StubPropertySource
	 * @see org.springframework.web.context.support.WebApplicationContextUtils#initServletPropertySources
	 */
	protected void initPropertySources() {
		// For subclasses: do nothing by default.
	}

b> validateRequiredProperties()

验证请求属性,方法很简单,循环遍历,判断是否为Null,存在则直接抛出异常MissingRequiredPropertiesException,该异常为自定义异常类

	public void validateRequiredProperties() {
        // 创建异常信息
        MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
        Iterator var2 = this.requiredProperties.iterator();
        
        // 遍历 找到空的key
        while(var2.hasNext()) {
            String key = (String)var2.next();
            if (this.getProperty(key) == null) {
                ex.addMissingRequiredProperty(key);
            }
        }
	    // 存在空的直接抛出异常
        if (!ex.getMissingRequiredProperties().isEmpty()) {
            throw ex;
        }
    }

<2> obtainFreshBeanFactory() 获取bean工厂

该方法很简单,获取到对应的bean工厂,类型为DefaultListableBeanFactory,也是Spring中功能最全的IOC容器

	/**
	 * Tell the subclass to refresh the internal bean factory.
	 * @return the fresh BeanFactory instance 返回容器示例
	 * @see #refreshBeanFactory()
	 * @see #getBeanFactory()
	 */
	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
         // 刷新容器
		refreshBeanFactory();
         // 通过getter方法获取到Bean工厂返回,其实就是默认的DefaultListableBeanFactory
		return getBeanFactory();
	}

a> refreshBeanFactory()

GenericApplicationContext类初始化的时候,就创建了一个默认的BeanFactory,然后这里会设置Id

  1. 创建的beanFactory是DefaultListableBeanFactory类型
  2. 该beanFactory在类初始化的时候就创建了
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
	// 构造方法
	public GenericApplicationContext() {
         // 这里也代表了DefaultListableBeanFactory是Spring中最核心的类
		this.beanFactory = new DefaultListableBeanFactory();
	}

    /**
	 * Do nothing: We hold a single internal BeanFactory and rely on callers
	 * to register beans through our public methods (or the BeanFactory's).
	 * @see #registerBeanDefinition
	 */
	@Override
	protected final void refreshBeanFactory() throws IllegalStateException {
		if (!this.refreshed.compareAndSet(false, true)) {
			throw new IllegalStateException(
					"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
		}
         // 这个id就是 org.springframework.context.annotation.AnnotationConfigApplicationContext@5b0abc94
		this.beanFactory.setSerializationId(getId());
	}	
    
 	// ...   
}

<3> prepareBeanFactory() 准备工厂

3、prepareBeanFactory(beanFactory);BeanFactory的预准备工作(BeanFactory进行一些设置);
	1)、设置BeanFactory的类加载器、支持表达式解析器...
	2)、添加部分BeanPostProcessor【ApplicationContextAwareProcessor】
	3)、设置忽略的自动装配的接口EnvironmentAware、EmbeddedValueResolverAware、xxx;
	4)、注册可以解析的自动装配;我们能直接在任何组件中自动注入:
			BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
	5)、添加BeanPostProcessor【ApplicationListenerDetector】
	6)、添加编译时的AspectJ
	7)、给BeanFactory中注册一些能用的组件;
		environment【ConfigurableEnvironment】、
		systemProperties【Map<String, Object>】、
		systemEnvironment【Map<String, Object>
	/**
	 * Configure the factory's standard context characteristics,  配置工厂启动时上下文特征
	 * such as the context's ClassLoader and post-processors.	  例如容器的类加载器和后置处理器
	 * @param beanFactory the BeanFactory to configure
	 */
	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Tell the internal bean factory to use the context's class loader etc.
         // 1.设置Bean的类加载器
		beanFactory.setBeanClassLoader(getClassLoader());
		if (!shouldIgnoreSpel) {
             // 设置支持相关表达式语言的解析器
			beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		}
         // 添加属性的编辑注册器
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
         // 2.添加部分后置处理器【ApplicationContextAwareProcessor】
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
         // 3.设置忽略自动装配的接口
		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.ignoreDependencyInterface(ApplicationStartupAware.class);

		// BeanFactory interface not registered as resolvable type in a plain factory.
		// MessageSource registered (and found for autowiring) as a bean.
         // 4.注册可以解析的自动装配
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

		// Register early post-processor for detecting inner beans as ApplicationListeners.
         // 5.添加BeanPostProcessor【ApplicationListenerDetector】事件监听
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// Detect a LoadTimeWeaver and prepare for weaving, if found.
		if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// Set a temporary ClassLoader for type matching.
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}

		// Register default environment beans.
         // 给BeanFactory中注册一些能用的组件
		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
		if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
			beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
		}
	}

<4> postProcessBeanFactory() 子类重写扩展

提供的扩展机制,子类通过重写这个方法来在BeanFactory创建并预准备完成以后做进一步的设置

	/**
	 * Modify the application context's internal bean factory after its standard
	 * initialization. All bean definitions will have been loaded, but no beans
	 * will have been instantiated yet. This allows for registering special
	 * BeanPostProcessors etc in certain ApplicationContext implementations.
	 * @param beanFactory the bean factory used by the application context
	 */
	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	}

<5> invokeBeanFactoryPostProcessors()

a> 方法入口

这个方法会继续调用一个包装类中的方法,负责执行后置处理器,其中的参数getBeanFactoryPostProcessors()会获取后置处理器,这里获取的后置处理器是框架初始化需要的,会被优先执行

但需要注意的是,并不是Spring框架需要的,在实际测试过程中,如果使用SpringBoot,可以成功获取到,如果单独启动Spring,则啥也没有

	/**
	 * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
	 * respecting explicit order if given.
	 * <p>Must be called before singleton instantiation.
	 */
	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
         // 执行后置处理器
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

		// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
		// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
		if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
	}

在这里插入图片描述
在这里插入图片描述

上面两张图也说明了问题,如果想在Spring框架基础上封装其它框架,例如经典的SpringBoot,Spring会先执行SpringBoot初始化需要的后置处理器,保证核心框架先顺利启动,然后再执行其它依赖和手写的后置处理器

当然侧面证明了Spring提供的良好的扩展性能,再启动Spring的时候,优先执行二次封装的代码,最后在是其它依赖和自己写的代码

b> 接口介绍

下面方法会用到这2个接口,这里先介绍一下

BeanFactoryPostProcessor

BeanFactoryPostProcessor的执行时机为容器初始化后,实例化Bean前,Spring允许在这个时候可以对Bean工厂进行修改,一种良好的扩展性能

public interface BeanFactoryPostProcessor {
	// 通过参数ConfigurableListableBeanFactory可以获取到定义信息
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

使用示例

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("调用MyBeanFactoryPostProcessor的postProcessBeanFactory");
        BeanDefinition bd = beanFactory.getBeanDefinition("mathCalculator");
        System.out.println("属性值------>" + bd.getPropertyValues().toString());
        MutablePropertyValues pv = bd.getPropertyValues();
        if (pv.contains("remark")) {
            pv.addPropertyValue("remark", "把备注信息修改一下");
        }
        bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
    }
}
BeanDefinitionRegistryPostProcessor
  1. 通过下面的代码,看到它继承了BeanFactoryPostProcessor
  2. 它会在所有的bean定义信息还未被加载,将要被加载的时候执行,可以对BeanDefiniton进行增删改查
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

	/**
	 * Modify the application context's internal bean definition registry after its
	 * standard initialization. All regular bean definitions will have been loaded,
	 * but no beans will have been instantiated yet. This allows for adding further
	 * bean definitions before the next post-processing phase kicks in.
	 * @param registry the bean definition registry used by the application context
	 * @throws org.springframework.beans.BeansException in case of errors
	 */
	void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}

c> 方法分析

  1. 首先参数传递过来的后置处理器,该参数上面已经介绍了,这些是框架启动需要的,例如SpringBoot,如果是单独的Spring启动则为空集合
  2. 判断是否实现了BeanDefinitionRegistry该接口,只有IOC容器实现了该接口,才代表允许其它代码操作BeanDefinition,看成一个开关入口
  3. 执行第1步:首先执行SpringBoot框架需要的BeanDefinitionRegistryPostProcessor,需要先把框架处理完毕
  4. 执行第2步:执行其它依赖和开发人员写的BeanDefinitionRegistryPostProcessor
    1. 优先执行实现了PriorityOrdered接口的
    2. 次之执行实现了Ordered接口的
    3. 执行剩余的后置处理器
  5. 接下来会先执行一批BeanFactoryPostProcessor,上面也介绍了这2个接口是继承关系,所以重写子类方法必须也带上父类方法,上面执行的BeanDefinitionRegistryPostProcessor后置处理器,肯定也有BeanFactoryPostProcessor的方法,这里需要执行,这里启动就是2部分
    1. 先执行上面这些实现了BeanDefinitionRegistryPostProcessor接口,里面肯定重写了父类BeanFactoryPostProcessor,需要先执行
    2. 参数传递过来的BeanFactoryPostProcessor,这些也需要先执行
  6. 到此上面已经把BeanDefinitionRegistryPostProcessor处理完毕,接下来就是BeanFactoryPostProcessor,这里会和上面一样,先处理PriorityOrdered,次之Ordered,最后剩余的
  7. 总结:代码非常长,理解了很简答,总体思想就是先执行框架启动需要的,然后在执行自己写的,先执行BeanDefinitionRegistryPostProcessor,后BeanFactoryPostProcessor
public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
         // 执行BeanDefinitionRegistryPostProcessors的实现类【首先调用】
		Set<String> processedBeans = new HashSet<>();
			
   		// 实现该接口才允许操作BeanDefinition,当然DefaultListableBeanFactory肯定实现了
		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
             
			// <1> 处理参数传递过来的后置处理器,这些是Spring启动需要的
             // 按照实现接口分类存进去, 并且优先执行实现了BeanDefinitionRegistryPostProcessor的后置方法,系统类的先执行
             for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
				else {
					regularPostProcessors.add(postProcessor);
				}
			}

			// Do not initialize FactoryBeans here: We need to leave all regular beans
			// uninitialized to let the bean factory post-processors apply to them!
			// Separate between BeanDefinitionRegistryPostProcessors that implement
			// PriorityOrdered, Ordered, and the rest.
             // 定义一个变量,用于后续分批执行代码
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
             // 第一步 执行实现了 PriorityOrdered 优先级排序接口的BeanDefinitionRegistryPostProcessors子类
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
			currentRegistryProcessors.clear();

			// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
             // 第二步 执行实现了Ordered顺序接口的BeanDefinitionRegistryPostProcessors
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
			currentRegistryProcessors.clear();

			// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
              // 最后 执行剩余的BeanDefinitionRegistryPostProcessors
			boolean reiterate = true;
			while (reiterate) {
				reiterate = false;
				postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
				for (String ppName : postProcessorNames) {
					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, beanFactory.getApplicationStartup());
				currentRegistryProcessors.clear();
			}

			// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
             // 调用到目前为止处理的所有处理器的 postProcessBeanFactory() 回调
             // 这里会有一个疑问: postProcessBeanFactory()不是下面很多行代码负责执行吗?咋这里就执行了
             // 首先 registryProcessors是上面实现了子类接口,那么父类肯定也给重写,那么这里先调用
             // 其次 regularPostProcessors到目前位置有数据,肯定是框架启动需要的后置处理器,也要先执行
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

		else {
			// Invoke factory processors registered with the context instance.
             // 否则执行框架启动需要的后置处理器
			invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
		}
		 
    	// 获取所有的 BeanFactoryPostProcessor 后置处理器
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

		// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (processedBeans.contains(ppName)) {
				// skip - already processed in first phase above
			}
			else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
         // 第一步 执行实现 PriorityOrdered 接口的 BeanFactoryPostProcessors
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
         // 第二步 执行实现 Ordered 接口的 BeanFactoryPostProcessors
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// Finally, invoke all other BeanFactoryPostProcessors.
         // 第三步 执行剩余的
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

		// Clear cached merged bean definitions since the post-processors might have
		// modified the original metadata, e.g. replacing placeholders in values...
		beanFactory.clearMetadataCache();
	}

d> 重要Debug

如下截图所示,Spring框架负责解析@Configuration配置类的是后置处理器ConfigurationClassPostProcessor,它会负责扫描各种类,把bean包装成BeanDefinition存入IOC容器,具体后续会介绍ConfigurationClassPostProcessor
在这里插入图片描述

<6> registerBeanPostProcessors()

顾名思义,注册Bean后置处理器,它负责拦截Bean的创建,这样我们就可以通过该拦截对Bean添加自定义逻辑,例如Aop功能,就是通过注解添加了一个后置处理器,然后在创建Bean的时候,对其进行代理,达到增强的目的

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
   PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
  1. 获取所有的BeanPostProcessor后置处理器
  2. 先注册PriorityOrdered优先级接口的BeanPostProcessor
  3. 再注册Ordered接口的
  4. 最后注册没有实现任何优先级接口的
  5. 最终注册MergedBeanDefinitionPostProcessor
  6. 注册一个ApplicationListenerDetector
public static void registerBeanPostProcessors(
      ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

   // 1.获取所有实现 BeanPostProcessor 接口的后置处理器
   String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

   // 2.记录数量 = 框架中已经存在的 + 稍后会注入的数量 + 下一行代码注入的1个后置处理器
   int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
   // 新注册的处理器 BeanPostProcessorChecker 主要用于记录信息
   beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

   // Separate between BeanPostProcessors that implement PriorityOrdered,
   // Ordered, and the rest.
   // 3.分类存储
   // 实现PriorityOrdered接口的
   List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
   List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
   // 实现Ordered接口的name集合
   List<String> orderedPostProcessorNames = new ArrayList<>();
   // 定义普通的name集合
   List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    
   for (String ppName : postProcessorNames) {
      if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
         BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
         priorityOrderedPostProcessors.add(pp);
         if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
         }
      }
      else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
         orderedPostProcessorNames.add(ppName);
      }
      else {
         nonOrderedPostProcessorNames.add(ppName);
      }
   }

   // 4.先注册实现 PriorityOrdered 接口的
   // First, register the BeanPostProcessors that implement PriorityOrdered.
   sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
   registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

   // 5.次之注册实现 Ordered 接口的
   // Next, register the BeanPostProcessors that implement Ordered.
   List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
   for (String ppName : orderedPostProcessorNames) {
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      orderedPostProcessors.add(pp);
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
         internalPostProcessors.add(pp);
      }
   }
   sortPostProcessors(orderedPostProcessors, beanFactory);
   registerBeanPostProcessors(beanFactory, orderedPostProcessors);
	
   // 5.最后注册普通的后置处理器
   // Now, register all regular BeanPostProcessors.
   List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
   for (String ppName : nonOrderedPostProcessorNames) {
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      nonOrderedPostProcessors.add(pp);
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
         internalPostProcessors.add(pp);
      }
   }
   registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

   // 6.注册实现了 MergedBeanDefinitionPostProcessor 接口的
   // Finally, re-register all internal BeanPostProcessors.
   sortPostProcessors(internalPostProcessors, beanFactory);
   registerBeanPostProcessors(beanFactory, internalPostProcessors);

   // Re-register post-processor for detecting inner beans as ApplicationListeners,
   // moving it to the end of the processor chain (for picking up proxies etc).
   // 7.重新注册用于将内部 bean 检测为 ApplicationListeners 的后处理器,将其移动到处理器链的末尾(用于获取代理等)
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

<7> initMessageSource() 国际化

MessageSource是负责国际化功能的,下面的代码大体很简单,如果已经存在国际化组件,就一顿操作处理,没有就注册个新的

那么想一下,之前怎么可能会有该bean?那肯定是开发人员自定义的国际化组件,如果存在则在第<5>步的时候已经解析完毕,执行到该方法,肯定就可以获取到

那么在把下面这个方法概述一下:如果开发人员自定义了国际化组件,那就用自己写的,按照固定的格式处理一下,否则就用默认的国际化组件

这同样体现了Spring框架良好的扩展机制,后续会编写单独的文章介绍MessageSource

protected void initMessageSource() {
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   // 如果存在该bean,则代表开发人员自定义了国家化组件
   if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
      this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
      // Make MessageSource aware of parent MessageSource.
      if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
         HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
         if (hms.getParentMessageSource() == null) {
            // Only set parent context as parent MessageSource if no parent MessageSource
            // registered already.
            hms.setParentMessageSource(getInternalParentMessageSource());
         }
      }
      if (logger.isTraceEnabled()) {
         logger.trace("Using MessageSource [" + this.messageSource + "]");
      }
   }
   else { // 否则使用默认的国际化组件
      // Use empty MessageSource to be able to accept getMessage calls.
      DelegatingMessageSource dms = new DelegatingMessageSource();
      dms.setParentMessageSource(getInternalParentMessageSource());
      this.messageSource = dms;
      beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
      if (logger.isTraceEnabled()) {
         logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
      }
   }
}

<8> initApplicationEventMulticaster()

下面这个方法大体逻辑和第<7>步一致,如果存在该bean,则代表开发人员自定义了该功能,则处理一下,否则注册一个默认的

ApplicationEventMulticaster是Spring中事件广播器接口,负责事件的广播发布。

通过名字可以看出它就是一个广播站,可以把监听器注册到我这里来,有事件通过我进行发布。也可以理解为MQ种的发布-订阅模式,监听器在这里进行订阅,有消息通过我进行发布

protected void initApplicationEventMulticaster() {
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   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.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() + "]");
      }
   }
}
ApplicationEventMulticaster

上面看懂了该组件的功能,这里看接口就好理解了,负责注册监听器的,负责发布事件的

public interface ApplicationEventMulticaster {
	
   // 注册监听器
   void addApplicationListener(ApplicationListener<?> listener);
   void addApplicationListenerBean(String listenerBeanName);
  
   // 移除监听器
   void removeApplicationListener(ApplicationListener<?> listener);
   void removeApplicationListenerBean(String listenerBeanName);
   void removeAllListeners();

   // 发布事件
   void multicastEvent(ApplicationEvent event);
   void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);

}

<9> onRefresh() 子类重写扩展

在特定上下文子类中初始化其他特殊bean

protected void onRefresh() throws BeansException {
   // For subclasses: do nothing by default.
}

<10> registerListeners()

在上面第<8>步,注册了一个事件广播器,该方法负责把监听器注册到里面

protected void registerListeners() {
    
   // 1.向事件分发器注册监听器,这些是通过配置文件读取的
   // Register statically specified listeners first.
   for (ApplicationListener<?> listener : getApplicationListeners()) {
      getApplicationEventMulticaster().addApplicationListener(listener);
   }

   // 2.向事件分发器注册外部加入的监听器,但不实例化
   // Do not initialize FactoryBeans here: We need to leave all regular beans
   // uninitialized to let post-processors apply to them!
   String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
   for (String listenerBeanName : listenerBeanNames) {
      getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
   }

   // 3.发布早期的事件
   // Publish early application events now that we finally have a multicaster...
   Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
   this.earlyApplicationEvents = null;
   if (earlyEventsToProcess != null) {
      for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
         getApplicationEventMulticaster().multicastEvent(earlyEvent);
      }
   }
}

<11> finishBeanFactoryInitialization()

通过名字可以看出是完成BeanFactory的初始化,一个收尾方法,相当于一个bean工厂大部分已经完成了,还剩余零零散散的辅助bean需要依次注入

在这个方法中需要关注的是最后1行,这里会实例化未设置懒加载的单例bean

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    
   // 1.为此上下文初始化转换服务
   // Initialize conversion service for this context.
   if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
         beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
      beanFactory.setConversionService(
            beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
   }

   // Register a default embedded value resolver if no bean post-processor
   // (such as a PropertyPlaceholderConfigurer bean) registered any before:
   // at this point, primarily for resolution in annotation attribute values.
   // 2.如果之前没有注册任何 bean 后处理器(例如 PropertyPlaceholderConfigurer bean),则注册一个默认的嵌入值解析器:此时,主要用于注释属性值的解析
   if (!beanFactory.hasEmbeddedValueResolver()) {
      beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
   }

   // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
   // 3.通过 getBean() 尽早的注册LoadTimeWeaverAware
   String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
   for (String weaverAwareName : weaverAwareNames) {
      getBean(weaverAwareName);
   }

   // Stop using the temporary ClassLoader for type matching.   
   // 4.停止使用临时类加载器进行类型匹配
   beanFactory.setTempClassLoader(null);

   // Allow for caching all bean definition metadata, not expecting further changes. 
   // 5.允许缓存所有 bean 定义元数据,而不是期望进一步的更改
   beanFactory.freezeConfiguration();

   // 6.Instantiate all remaining (non-lazy-init) singletons.
   // 初始化未懒加载的单例bean
   beanFactory.preInstantiateSingletons();
}

a> preInstantiateSingletons

子类DefaultListableBeanFactory重写了该方法

功能:循环所有的Bean名称,遍历判断,然后实例化,最后调用回调

// DefaultListableBeanFactory	

	@Override
	public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}

		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
         // 1.获取全部的BeanName
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
         // 2.实例化所有非懒加载的单实例Bean
		for (String beanName : beanNames) 
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
             // 非抽象 && 单实例 && 非懒加载
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                 // 类型判断是否为FactoryBean,  FactoryBean在后续章节也有讲解
				if (isFactoryBean(beanName)) {
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged(
									(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				else {
                      // 普通的Bean在这里直接获取
					getBean(beanName);
				}
			}
		}

		// Trigger post-initialization callback for all applicable beans...
		// 触发所有适用 bean 的初始化后回调
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}

<12> finishRefresh()

上面已经把BeanFactory初始化完毕,那么这个IOC容器就接近尾声了,接下来就是一些后续工作

protected void finishRefresh() {
   // Clear context-level resource caches (such as ASM metadata from scanning).
   // 清除上下文级资源缓存
   clearResourceCaches();

   // Initialize lifecycle processor for this context.
   // 为此上下文初始化生命周期处理器
   initLifecycleProcessor();

   // Propagate refresh to lifecycle processor first.
   getLifecycleProcessor().onRefresh();

   // Publish the final event.
   publishEvent(new ContextRefreshedEvent(this));

   // Participate in LiveBeansView MBean, if active.
   LiveBeansView.registerApplicationContext(this);
}

ingleton) {
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}


## <12> finishRefresh()

上面已经把`BeanFactory`初始化完毕,那么这个IOC容器就接近尾声了,接下来就是一些后续工作

```java
protected void finishRefresh() {
   // Clear context-level resource caches (such as ASM metadata from scanning).
   // 清除上下文级资源缓存
   clearResourceCaches();

   // Initialize lifecycle processor for this context.
   // 为此上下文初始化生命周期处理器
   initLifecycleProcessor();

   // Propagate refresh to lifecycle processor first.
   getLifecycleProcessor().onRefresh();

   // Publish the final event.
   publishEvent(new ContextRefreshedEvent(this));

   // Participate in LiveBeansView MBean, if active.
   LiveBeansView.registerApplicationContext(this);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为人师表好少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值