前言 在讲 beanFactory 架构时说过,接口ConfigurableBeanFactory
表明 bean 工厂是可配置的,为了让用户能方便的配置 bean 工厂,Spring 设计了代表 Spring 容器的顶级接口ApplicationContext
。如果说 bean 工厂负责管理 bean 的生命周期,提供的扩展能力是对 bean 的定制,那么 Spring 容器则站在更高的维度,提供对 bean 工厂的定制能力以及应用维度的事件发布和消费能力等:
支持多种 Spring 配置方式来构建 beanFactory
轻松定制 beanFactory
支持应用事件广播和监听
ApplicationContext 架构 基础类 ApplicationContext 顶层接口,用来指代一个 Spring 容器,getAutowireCapableBeanFactory
方法用来获取一个可依赖注入的 bean 工厂,可见 Spring 容器的核心就是包了一个基础的 bean 工厂
ConfigurableApplicationContext 继承ApplicationContext
,描述一个可配置 beanFactory 的 Spring 容器,定义配置方法,例如添加 bfppaddBeanFactoryPostProcessor
、添加应用事件监听器addApplicationListener
类比ConfigurableBeanFactory
,描述的是可配置的 bean 工厂,实现对 bean 加载过程的定制,例如给 bean 工厂配置 bpp。对于 Spring 容器而言,它的可配置体现在对 bean 工厂本身的定制化,因此提供的扩展是 bean 工厂处理器 bfpp。需要说明的是,bfpp 虽然定制的是 bean 工厂,但最终还是通过 bean 工厂影响 bean,本质上还是对 bean 加载过程的定制
定义核心方法refresh
,用来刷新(初始化)Spring 容器。大部分具体的 Spring 容器实现类都会在构造函数里调用该方法实现容器的初始化 定义核心方法close
,关闭 Spring 容器时调用
AbstractApplicationContext ConfigurableApplicationContext
的实现类,描述了一个可配置的 Spring 容器,它做到了这些事情:
可添加 bfpp、应用事件监听器
实现了refresh
方法,框定了 Spring 容器初始化的流程,该方法的实现后面会详细介绍
实现了close
方法,框定了 Spring 容器关闭的流程,执行所有单例 bean 的销毁生命周期
ConfigurableApplicationContext 在 refresh 方法里定义了一些模板方法,需要子类在容器初始化过程中做这些事情:
实现模板方法refreshBeanFactory
,构建一个 DefaultListableBeanFactory。根据对该方法的不同实现方式,可以将子类容器分为两大类,Refreshable 的容器和 Generic 的容器
,区别是 Refreshable 容器真正实现了该模板方法,所以每次调用 refresh 方法,都会重新构建 bf,而 Generic 容器做了个空实现,实际在构造函数里先构建好 bf,所以调用 refresh 方法不会再重新构建 bf
实现模板方法closeBeanFactory
,Spring 容器关闭时调用。这个目前子类容器也没有特殊的实现
实现模板方法postProcessBeanFactory
,容器初始化过程中后置处理构建好的 bf
核心类 ClassPathXmlApplicationContext 基于 XML 构建 bf 的 refreshable 的 Spring 容器,实现 refreshBeanFactory 方法,每次调用 refresh 都会基于 xml 构建 bf
AnnotationConfigWebApplicationContext 基于注解构建 bf 的 refreshable 的 Spring 容器,实现 refreshBeanFactory 方法,每次调用 refresh 都会基于 配置类 构建 bf
GenericXmlApplicationContext 基于 XML 构建 bf 的 generic 的 Spring 容器,refreshBeanFactory 方法做空实现,构造函数里基于 xml 构建 bf,调用 refresh 不会再次构建 bf
AnnotationConfigApplicationContext 基于 注解 构建 bf 的 generic 的 Spring 容器,refreshBeanFactory 方法做空实现,构造函数里基于 配置类 构建 bf,调用 refresh 不会再次构建 bf
基于注解构建 bf 的说明 如果是基于注解的 Spring 容器,无论是 refreshable 的还是 generic 的,注册业务 bean 的 bd 前,都会提前向 bf 注册支持注解驱动的一些内部 bean 的 bd,重点有这么几个 bean:
ConfigurationClassPostProcessor
负责注册通过配置类 bean(@Configuration 修饰)间接定义的所有 bd 到 bf
AutowiredAnnotationBeanPostProcessor
bpp,依赖注入阶段加载并注入@Autowired 修饰的 bean,解析得到@Value 的实际值并注入到成员变量
CommonAnnotationBeanPostProcessor
bpp,依赖注入阶段加载并注入@Resource 修饰的 bean
see:org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)
总结 ApplicationContext 架构的 UML 类图:
综上,ApplicationContext
架构主要使用了适配器模式
、模板模式
ApplicationContext
通过在内部持有一个DefaultListableBeanFactory
,适配了 BeanFactory 接口
Spring 容器的刷新主流程在上层抽象类的 refresh 方法中实现。同时定义创建 bean 工厂的模板方法refreshBeanFactory
,有两套 bean 工厂创建流程,分别由子类AbstractRefreshableApplicationContext
和GenericApplicationContext
实现
AbstractRefreshableApplicationContext
类和GenericApplicationContext
类都有自己的子类,分别支持 xml 方式和注解方式的 beanDefinition 注册
初始化 Spring 容器 容器在实例化完成后,一般会接着调用 refresh 方法初始化,或者直接在构造函数里就调用 refresh 方法,下面详述容器初始化流程
定制系统变量 回调模板方法initPropertySources
,由三方实现,可以添加系统变量、设置哪些系统变量是必须的(不存在直接抛异常)
1 2 3 4 5 6 // Initialize any placeholder property sources in the context environment. initPropertySources(); // Validate that all properties marked as required are resolvable: // see ConfigurablePropertyResolver#setRequiredProperties getEnvironment().validateRequiredProperties();
1 2 3 4 5 6 7 8 9 10 11 public void validateRequiredProperties() { MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException(); for (String key : this.requiredProperties) { if (this.getProperty(key) == null) { ex.addMissingRequiredProperty(key); } } if (!ex.getMissingRequiredProperties().isEmpty()) { throw ex; } }
测试代码:applicationcontext.RequiredPropertyTest
构建 DefaultListableBeanFactory 构建 Spring 容器的 DefaultListableBeanFactory,提供refreshBeanFactory
模板方法,由子类实现,创建一个已经完成 beanDefinition 解析和注册的 bean 工厂。上面说过,只有 refreshable 的 Spring 容器在这里构建 bf
1 2 3 4 5 6 7 8 protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }
显式配置 DefaultListableBeanFactory 注册 SPEL 解析器 显式注册解析 SpEL 的StandardBeanExpressionResolver
,该 resolver 会在 bean 属性赋值前被调用来解析配置属性的 SpEL 表达式
1 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
注册属性编辑注册器 显式注册ResourceEditorRegistrar
,注册器会在 Bean 加载阶段被调用,给 BeanWrapper 注册一些 IO 类型的PropertyEditor
1 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Override public void registerCustomEditors(PropertyEditorRegistry registry) { ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver); doRegisterEditor(registry, Resource.class, baseEditor); doRegisterEditor(registry, ContextResource.class, baseEditor); doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor)); doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor)); doRegisterEditor(registry, File.class, new FileEditor(baseEditor)); doRegisterEditor(registry, Path.class, new PathEditor(baseEditor)); doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor)); doRegisterEditor(registry, URL.class, new URLEditor(baseEditor)); ClassLoader classLoader = this.resourceLoader.getClassLoader(); doRegisterEditor(registry, URI.class, new URIEditor(classLoader)); doRegisterEditor(registry, Class.class, new ClassEditor(classLoader)); doRegisterEditor(registry, Class[].class, new ClassArrayEditor(classLoader)); if (this.resourceLoader instanceof ResourcePatternResolver) { doRegisterEditor(registry, Resource[].class, new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader, this.propertyResolver)); } }
如果用户想添加自定义的PropertyEditor
,可以简单覆盖PropertyEditorSupport
的setAsText
方法来自定义一个PropertyEditor
,再创建它的注册器PropertyEditorRegistrar
,然后配置一个CustomEditorConfigurer
Bean,在 propertyEditorRegistrars 属性中加入这个 Registrar。CustomEditorConfigurer
是 bfpp,在 beanFactory 后置处理中将PropertyEditorRegistrar
注册到 BeanFactory
注册 ApplicationContextAwareProcessor 显式注册 bpp:ApplicationContextAwareProcessor
,它的作用是 bean 前置初始化时,为 bean 自动注入 Aware 方式指定的 Spring 容器组件
1 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 private void invokeAwareInterfaces(Object bean) { if (bean instanceof Aware) { if (bean instanceof EnvironmentAware) { ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment()); } if (bean instanceof EmbeddedValueResolverAware) { ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver); } if (bean instanceof ResourceLoaderAware) { ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext); } if (bean instanceof ApplicationEventPublisherAware) { ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext); } if (bean instanceof MessageSourceAware) { ((MessageSourceAware) bean).setMessageSource(this.applicationContext); } if (bean instanceof ApplicationContextAware) { ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); } } }
注册 ApplicationListenerDetector 显式注册 bpp:ApplicationListenerDetector
,作用是对于类型为ApplicationListener
子类的 bean,后置初始化处理时注册到 ApplicationContext。这些应用事件监听器最终会被注册到事件组播器ApplicationEventMulticaster
。Spring 容器关闭时,ApplicationListenerDetector
会在 bean 销毁前置回调时,将其从ApplicationEventMulticaster
里移除
1 beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (bean instanceof ApplicationListener) { // potentially not detected as a listener by getBeanNamesForType retrieval Boolean flag = this.singletonNames.get(beanName); if (Boolean.TRUE.equals(flag)) { // singleton bean (top-level or inner): register on the fly this.applicationContext.addApplicationListener((ApplicationListener<?>) bean); } else if (Boolean.FALSE.equals(flag)) { ... } } return bean; }
1 2 3 4 5 6 7 8 9 10 11 12 13 @Override public void postProcessBeforeDestruction(Object bean, String beanName) { if (bean instanceof ApplicationListener) { try { ApplicationEventMulticaster multicaster = this.applicationContext.getApplicationEventMulticaster(); multicaster.removeApplicationListener((ApplicationListener<?>) bean); multicaster.removeApplicationListenerBean(beanName); } catch (IllegalStateException ex) { // ApplicationEventMulticaster not initialized yet - no need to remove a listener } } }
注册 environment 相关 bean 到 BeanFactory 注册 ConfigurableEnvironment 到 bf 通过 environment 可以拿到 map 类型的 JVM 参数和系统环境变量,这两个 map 也一并注册到 bf
1 2 3 4 5 6 7 8 9 10 11 if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { // JVM参数 beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { // 环境变量 beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); }
后置处理 bf 提供模板方法后置处理 bf 提供模板方法 postProcessBeanFactory,由AbstractApplicationContext
的子类(可由用户实现)覆写,后置处理 beanFactory
1 postProcessBeanFactory(beanFactory);
调用 bfpp 执行 bean 工厂后置处理 bfpp 的来源 1、调用方法addBeanFactoryPostProcessor
显式注册到 AbstractApplicationContext
注意,Spring 提供的容器没有调该方法添加任何 bfpp,可以理解为是给用户自定义容器用的。但要保证该方法必须在 refresh 方法前被调用,否则不起作用
1 2 3 4 5 @Override public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) { Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null"); this.beanFactoryPostProcessors.add(postProcessor); }
2、通过 bd 走 bean 加载流程得到的 bfpp。AbstractApplicationContext
会从 bf 的全局 bd 里枚举 bfpp 的 beanName,然后加载 bfpp
这细分为两类,一类是用户自己注册的 BeanFactoryPostProcessor bean,另一类是 Spring 注册内部的 bfpp 的 bd 到 bf,ConfigurationClassPostProcessor
就是这种方式注册的
1 2 3 4 5 postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { ... ... beanPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); }
bfpp 的调用顺序 1、调用显式注册的BeanDefinitionRegistryPostProcessor
的子类的postProcessBeanDefinitionRegistry
方法
BeanDefinitionRegistryPostProcessor 是 bfpp 的子接口,定义postProcessBeanDefinitionRegistry
方法,预处理 bd
1 2 3 4 5 6 7 8 9 10 11 for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; registryProcessor.postProcessBeanDefinitionRegistry(registry); registryProcessors.add(registryProcessor); } else { regularPostProcessors.add(postProcessor); } }
2、加载并调用 bd 注册到 bf 的BeanDefinitionRegistryPostProcessor
的子类的postProcessBeanDefinitionRegistry
方法
优先排序并执行实现了 PriorityOrdered 接口的 BeanDefinitionRegistryPostProcessor
排序使用的 comparator:AnnotationAwareOrderComparator
排序执行实现了 Ordered 接口的 BeanDefinitionRegistryPostProcessor
排序执行剩下的 BeanDefinitionRegistryPostProcessor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 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); // 执行Spring注册的BeanDefinitionRegistryPostProcessor,这里会执行ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. // 因为ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry会注册从ConfigurationBean发现的所有bean // 所以需要筛选出新增的BeanDefinitionRegistryPostProcessor,调用它的postProcessBeanDefinitionRegistry 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); currentRegistryProcessors.clear(); // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear. 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); currentRegistryProcessors.clear(); }
3、调用 BeanDefinitionRegistryPostProcessor 子类的 postProcessBeanFactory 方法,后置处理 bfpp
1 invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
4、调用显示注册的 bfpp 的 postProcessBeanFactory 方法,后置处理 bfpp
1 invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
5、加载并调用 bd 注册到 bf 的 bfpp 的 postProcessBeanFactory 方法,后置处理 bfpp
会 skip 上面已经调用过的 BeanDefinitionRegistryPostProcessor 子类和显示注册的 bfpp
依然是先排序后执行,优先 PriorityOrdered,其次 Ordered,再次剩下的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 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. sortPostProcessors(priorityOrderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // Next, invoke the BeanFactoryPostProcessors that implement Ordered. List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(); 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<>(); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
bfpp 的应用场景举例 ConfigurationClassPostProcessor
它是BeanDefinitionRegistryPostProcessor
的子类。基于注解的 Spring 容器会在构建 bf 阶段将 bd 注册进去。它的 postProcessBeanDefinitionRegistry 方法负责把配置类 bean 间接引入的所有 bean 的 bd 注册到 bf
CustomEditorConfigurer
用户可以配置这个 bean,bf 后置处理阶段,间接注册一组自定义的PropertyEditorRegistrar
到 bf
测试代码:populatebean.propertyeditor.PropertyEditorTest
PropertySourcesPlaceholderConfigurer
Spring 解析标签”context:property-placeholder”,注册 PPC:PropertySourcesPlaceholderConfigurer。bf 后置处理阶段,将 bd.pv 里定义的占位符替换为实际值
占位符替换优先级:JVM 参数->系统环境变量->应用配置文件
测试代码:populatebean.value.ValueTest#testPPC
加载并添加配置的 bpp 到 bf bpp 的来源只能通过配置方式,这也体现了 Spring 容器的定位,是面向 bf,而非面向 bean,所以如果需要 bpp,只能配置,不能直接通过 Spring 容器添加
优先注册实现了PriorityOrdered
、Ordered
接口的 bpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false); ... ... 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); } } ... ... sortPostProcessors(priorityOrderedPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); ... ... sortPostProcessors(orderedPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, orderedPostProcessors); ... ... registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
AutowiredAnnotationBeanPostProcessor 基于注解的 Spring 容器,例如AnnotationConfigApplicationContext
,在构造函数里就会给 bf 注册AutowiredAnnotationBeanPostProcessor
的 bd,然后在这个阶段加载并将其添加到 bf。该 bpp 的作用是在 bean 加载的依赖注入阶段,解析得到@Value 的实际值或者加载@Autowired 修饰的 依赖 bean,并反射注入
对于@Value,如果使用占位符,使用 StringValueResolver 来解析,如果使用 spel,使用 Spring 容器的 spel 解析器来解析
获取并添加应用事件组播器 ApplicationEventMulticaster 到 Spring 容器 如果 bf 有组播器的 bd,即用户注册了一个自己的组播器 bean,则直接加载后作为 Spring 容器的应用事件组播器。否则 new 一个 Spring 提供的默认组播器SimpleApplicationEventMulticaster
Spring 容器发布应用事件时使用组播器,它通过观察者模式组播应用事件给注册到它的事件监听器
1 2 3 4 5 6 7 8 9 ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); } else { this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); }
SimpleApplicationEventMulticaster 作为 Spring 容器默认的事件组播器,有如下特性:
1 2 3 4 5 6 7 protected boolean supportsEvent( ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) { GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ? (GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener)); return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType)); }
测试代码:applicationcontext.ApplicationListenerTest
将显式添加到容器的 ApplicationListener 添加到组播器 添加应用事件监听器ApplicationListener
到组播器ApplicationEventMulticaster
ApplicationListener
的来源渠道同 bfpp,显式添加到 Spring 容器 或配置为 bean。这里只将显式添加到 Spring 容器的 listener 注册到ApplicationEventMulticaster
配置的 listener bean,通过前面介绍的 bpp:ApplicationListenerDetector
,在 bean 后置初始化处理时添加到ApplicationEventMulticaster
1 2 3 4 5 6 7 8 9 10 11 12 protected void registerListeners() { // 显式注册到Spring容器的监听器,注册到应用事件组播器 for (ApplicationListener<?> listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); } // 通过注册的BD走bean加载的监听器,beanName注册到应用事件组播器 String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false); for (String listenerBeanName : listenerBeanNames) { getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } }
添加属性占位符解析器 StringValueResolver 到 bf StringValueResolver 把@Value 注解表达式中的“占位符”替换为实际值。如果 bean 工厂不存在占位符解析器StringValueResolver
,则添加一个 lambda 表达式实现的匿名 resolver 到 bf,底层使用PropertySourcesPropertyResolver
解析@Value 注解表达式中的占位符
注意,只有@Value 表达式用占位符,即”${xxx}”书写,才会依赖 StringValueResolver
解析@Value 并注入是通过上面介绍的 bpp:AutowiredAnnotationBeanPostProcessor
解析占位符用到的配置源包括:JVM 参数、系统环境变量、应用配置文件,优先级为
1 2 3 if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); }
如果 Spring 容器基于 XML 配置,且通过标签”context:property-placeholder”注册了PropertySourcesPlaceholderConfigurer
,在 bf 后置处理时,就会添加一个 Lambda 写的匿名StringValueResolver
到 bf,同时解析并替换 bd.pv 中的占位符。因此,上面判断 beanFactory.hasEmbeddedValueResolver() 就返回 true,不会再次添加 StringValueResolver
PropertySourcesPlaceholderConfigurer 给 bf 添加的 StringValueResolver 的配置源可以包含额外指定的应用配置文件
除了 xml 方式注册 PropertySourcesPlaceholderConfigurer,因为它就是一个 bfpp,所以也可以用户自己将其配置成 bean,添加一些 k-v 或者直接为 location 设置应用配置文件资源,作为配置源
测试代码:
populatebean.value.ValueTest#testPPC2
org.springframework.context.support.PropertySourcesPlaceholderConfigurerTests#replacementFromEnvironmentProperties
org.springframework.context.support.PropertySourcesPlaceholderConfigurerTests#localPropertiesViaResource
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { if (this.propertySources == null) { this.propertySources = new MutablePropertySources(); if (this.environment != null) { this.propertySources.addLast( new PropertySource<Environment>(ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME, this.environment) { @Override @Nullable public String getProperty(String key) { return this.source.getProperty(key); } } ); } try { PropertySource<?> localPropertySource = new PropertiesPropertySource(LOCAL_PROPERTIES_PROPERTY_SOURCE_NAME, mergeProperties()); if (this.localOverride) { this.propertySources.addFirst(localPropertySource); } else { this.propertySources.addLast(localPropertySource); } } catch (IOException ex) { throw new BeanInitializationException("Could not load properties", ex); } } processProperties(beanFactory, new PropertySourcesPropertyResolver(this.propertySources)); this.appliedPropertySources = this.propertySources; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, final ConfigurablePropertyResolver propertyResolver) throws BeansException { propertyResolver.setPlaceholderPrefix(this.placeholderPrefix); propertyResolver.setPlaceholderSuffix(this.placeholderSuffix); propertyResolver.setValueSeparator(this.valueSeparator); StringValueResolver valueResolver = strVal -> { String resolved = (this.ignoreUnresolvablePlaceholders ? propertyResolver.resolvePlaceholders(strVal) : propertyResolver.resolveRequiredPlaceholders(strVal)); if (this.trimValues) { resolved = resolved.trim(); } return (resolved.equals(this.nullValue) ? null : resolved); }; ... beanFactoryToProcess.embeddedValueResolvers.add(valueResolver); }
如果没注册 PropertySourcesPlaceholderConfigurer,则 xml 的标签里指定的占位符不会被替换,因为依赖注入阶段不会对 bd.pv 中的 value 做占位符解析处理。测试代码:
populatebean.value.ValueTest
加载单例 beans 预加载所有非懒加载的单例到 beanFactory(好处是提前暴露 bean 配置的错误)
如果加载的 bean 实现了SmartInitializingSingleton
接口,加载后回调 afterSingletonsInstantiated 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { ... ... else { getBean(beanName); } } } for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) { SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; ... ... smartSingleton.afterSingletonsInstantiated(); } }
Spring 容器初始化后置处理 此时 Spring 容器初始化流程已经结束,接下来进行的是容器初始化后置处理
回调 SmartLifecycle Bean 的 start 方法
有些 bean 在 Spring 容器初始化完成后要执行一些生命周期钩子函数
如果用户注册了实现LifecycleProcessor
接口的 bean,优先从 bd 获取并加载该 bean 作为 Spring 容器的生命周期处理器,否则创建默认的DefaultLifecycleProcessor
1 2 3 4 5 6 7 8 9 10 11 12 13 protected void initLifecycleProcessor() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) { this.lifecycleProcessor = beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class); } else { DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor(); defaultProcessor.setBeanFactory(beanFactory); this.lifecycleProcessor = defaultProcessor; beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor); } }
调用 LifecycleProcessor#onRefresh 方法,默认调用 DefaultLifecycleProcessor 的 onRefresh 方法,内部调用 startBeans 方法,参数 autoStartupOnly=true 该方法先将实现了SmartLifecycle
接口的 bean 分组,然后按分组号排序后,从小到大以组为维度调用组内部 SmartLifecycle bean 的 start 方法
SmartLifecycle bean 的 isAutoStartup 方法必须返回 true,才会回调 start 方法
如果调用 DefaultLifecycleProcessor#start 方法,参数 autoStartupOnly=false,会对所有的SmartLifecycle
和Lifeclcye
bean,分组后回调 start 方法
通过Phased
接口获得分组号,如果 SmartLifecycle bean 未实现该接口,则为 0 号
Spring 容器 close 时,按分组号从大到小回调 stop 方法,与 start 方法顺序相反
1 getLifecycleProcessor().onRefresh();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 private void startBeans(boolean autoStartupOnly) { Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans(); Map<Integer, LifecycleGroup> phases = new HashMap<>(); lifecycleBeans.forEach((beanName, bean) -> { if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) { int phase = getPhase(bean); LifecycleGroup group = phases.get(phase); if (group == null) { group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly); phases.put(phase, group); } group.add(beanName, bean); } }); if (!phases.isEmpty()) { List<Integer> keys = new ArrayList<>(phases.keySet()); Collections.sort(keys); for (Integer key : keys) { phases.get(key).start(); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, boolean autoStartupOnly) { Lifecycle bean = lifecycleBeans.remove(beanName); if (bean != null && bean != this) { String[] dependenciesForBean = getBeanFactory().getDependenciesForBean(beanName); // 优先启动所有Lifycycle bean依赖的lifecycle beans for (String dependency : dependenciesForBean) { doStart(lifecycleBeans, dependency, autoStartupOnly); } if (!bean.isRunning() && (!autoStartupOnly || !(bean instanceof SmartLifecycle) || ((SmartLifecycle) bean).isAutoStartup())) { try { // 启动lifecycle bean bean.start(); } ... ... } } }
组播 Spring 容器初始化完成事件 通过ApplicationEventMulticaster
组播ApplicationContext
的刷新完成事件ContextRefreshedEvent
到注册的ApplicationListener
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 publishEvent(new ContextRefreshedEvent(this)); ... ... protected void publishEvent(Object event, @Nullable ResolvableType eventType) { Assert.notNull(event, "Event must not be null"); ApplicationEvent applicationEvent; if (event instanceof ApplicationEvent) { applicationEvent = (ApplicationEvent) event; } else { applicationEvent = new PayloadApplicationEvent<>(this, event); if (eventType == null) { eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType(); } } ... ... getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); ... ... }
总结 综上,可以总结出 ApplicationContext 具备这些定制和扩展能力:
支持 SPEL
支持自定义 bean 属性编辑器
通过 bfpp 后置处理时把属性编辑注册器注册到 beanFactory
支持自定义 BeanFactoryPostProcessor
支持自定义 BeanPostProcessor
支持自定义发布和监听应用事件
配置方式自定义事件组播器,否则 Spring 容器提供默认的组播器
支持 Spring 容器在启动或停止时刻回调 LifeCycle bean 对应的生命周期方法