首先来看 SpringApplication 里刷新上下文的逻辑:
private void refreshContext(ConfigurableApplicationContext context) { refresh(context); if (this.registerShutdownHook) { try { context.registerShutdownHook(); } catch (AccessControlException ex) { // Not allowed in some environments. } } } protected void refresh(ApplicationContext applicationContext) { Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext); ((AbstractApplicationContext) applicationContext).refresh(); }
刷新的逻辑是在 AbstractApplicationContext.refresh
方法完成的,刷新完后注册了 JVM 的关闭回调钩子。
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // 让子类提供要刷新的 BeanFactory ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. // 核心逻辑:调用上下文里以Bean形式注册的所有 BeanFactoryPostProcessor invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. // 核心逻辑:向beanFactory注册 BeanPostProcessor, // 用于在创建 bean 时回调,以增强 bean registerBeanPostProcessor,s(beanFactory); // Initialize message source for this context. // 初始化 MessageSource initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. // 核心逻辑:实例化所有非延迟初始化的单例 finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. 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 { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } }
上下文刷新的核心逻辑在于:
1、 调用上下文里以 Bean 形式注册的所有 BeanFactoryPostProcessor。
对于 AnnotationConfigEmbeddedWebApplicationContext
和 AnnotationConfigApplicationContext
上下文,它们在构建的时候会创建 AnnotatedBeanDefinitionReader
, AnnotatedBeanDefinitionReader
在构造函数里会往上下文里注册一些基础组件,很重要的一个是 ConfigurationClassPostProcessor
,会在这里被调用,用于解析配置类、加载bean定义等。其他的具体见 AnnotationConfigUtils.registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, Object source)
方法。
2、 向 beanFactory
注册 BeanPostProcessor
,以这些 BeanPostProcessor
被应用的顺序注册的:
不同组件的实现有如下三类分类
1. 实现 PriorityOrdered 接口
2. 实现 Ordered 接口
3. 非继承上述两个接口的
执行顺序规则
1. PriorityOrdered -> Ordered -> 非继承上述接口的
2. 同一类实现的 order 值越低优先级越高
3、 实例化所有非延迟初始化的单例。
4、如果刷新的过程出现 BeansException 异常则销毁已创建的 bean、把上下文标记为未激活。
5、最终清理缓存。
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // 如果beanfactory里注册有ConversionService则使用 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)); } // 如果需要,添加一个EmbeddedValueResolver,主要用于处理注解属性的值(${}) if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(new StringValueResolver() { @Override public String resolveStringValue(String strVal) { return getEnvironment().resolvePlaceholders(strVal); } }); } // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early. String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } // Stop using the temporary ClassLoader for type matching. beanFactory.setTempClassLoader(null); // Allow for caching all bean definition metadata, not expecting further changes. // 冻结配置,使所有 bean 定义的元数据不再变化,从而可以缓存这些 beanFactory.freezeConfiguration(); // Instantiate all remaining (non-lazy-init) singletons. // 实例化剩余所有非延迟加载的单例 beanFactory.preInstantiateSingletons(); }
实例化 bean 之前的主要工作:
1. 指定 bean 类型转换类 ConversionService;
2. 准备一个 EmbeddedValueResolver 用于处理注解里的值( #{}/ ${}
);
3. 冻结配置,使 bean 定义不再变化,从而可以缓存它的的元数据。
欢迎关注我的微信公众号: coderbee笔记 ,可以更及时回复你的讨论。