1.容器和上下文:
1.bean工厂的创建:
DefaultListalbleBeanFactory是一个典型的bean工厂实现,这个类类图如下’:
一个bean工厂应该具备的能力:
1.基础能力,枚举bean,分层,自动装配,独立配置
2.注册单例bean包括beanFactory的能力
3.注册别名的能力
spring中创建的bean默认就是单例bean。
其优势实际上就是单例自身的各种优势:
- 减少系统新创建实例消耗的资源
- 减少jvm垃圾回收
- 可以从缓存中快速获取到bean
单例bean也存在缺点,主要表现在在并发环境下的线程不安全。
2.扩展点
spring 提供了很多的扩展点,主要用途在spring启动的过程中任意环节进行干预,实现自己的罗技,大概流程如下:
创建application -> 创建beanFactory-> 注册beanDefination-> 合并beanDefination->创建bean实例->填充 属性->初始化bean
spring给我们提供的常用的扩展点称为POSTProcessor,也叫后置器。而我们最常使用的BeanFactoryPostProcessor和BeanPostProcessor。
3.ApplicationContext
一个ApplicationContext继承了五个接口,共同为一个上下文赋能,这些接口我们都已经接触过了:
- EnvironmentCapable:提供一个上下文环境的能力
- ListableBeanFactory:枚举bean工厂的bean的能力
- HierarchicalBeanFactory:分层的能力
- MessageSource:国际化的能力
- ApplicationEventPublisher:发布事件的能力
我们可体会一下registerShutdownHook的用法,钩子函数就是在生命周期内会自动调用的一种函数,我们自己写一个容器类继承GenericApplicationContext:
public class MyGenericApplicationContext extends GenericApplicationContext {
private Thread shutdownHook = null;
@Override
public void registerShutdownHook() {
if (this.shutdownHook == null) {
// No shutdown hook registered yet.
this.shutdownHook = new Thread(SHUTDOWN_HOOK_THREAD_NAME) {
@Override
public void run() {
System.out.println("容器关闭了,该干啥干啥吧!");
}
};
Runtime.getRuntime().addShutdownHook(this.shutdownHook);
}
}
}
我们编写如下测试类,然后分析一下,我们注册的线程会在何时调用:
public class TestBeanFactory {
@Test
public void testXmlConfig() throws InterruptedException {
MyGenericApplicationContext myGenericApplicationContext = new MyGenericApplicationContext();
myGenericApplicationContext.registerShutdownHook();
System.out.println("before");
Thread.sleep(2000);
System.out.println("after");
}
}
结果:
before
after
容器关闭了,该干啥干啥吧!
所以整个apploicaitonContext的加载过程就如下所示: 先加载beandefination,然后刷新。
(TODO :加载beandifination的过程如下: 可以通过 xml文件的方式,带注解的bean,配置文件,类路径扫描等方式加载)
大体过程如下
public GenericXmlApplicationContext(Resource... resources) {
// 1、加载资源
load(resources);
// 2、刷新容器
refresh();
}
当然实现类内容和过程基本一致,如下
public AnnotationConfigApplicationContext(String... basePackages) {
this();
scan(basePackages);
refresh();
}
4.刷新容器
任何构建applicationContext的过程都是两步走: 获取元数据->刷新容器,
刷新容器的目的就是实例化我们的容器和容器内的bean,刷新容器是核心内容,要求在刷新前获取了全部=元数据,beanDefination也都已经准备好,保存在DefaultListableBeanFactory的map中
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
刷新容器的核心能力保留在AbstractApplicationContext类中,子类也可以去扩展,如spring mvc 、springboot等:
我们可以看一下在ServletWebServerApplicationContext中的扩展如下:核心还是父类的刷新能力,仅仅在容器启动失败后,将web服务关闭:
@Override
public final void refresh() throws BeansException, IllegalStateException {
try {
super.refresh();
}
catch (RuntimeException ex) {
WebServer webServer = this.webServer;
if (webServer != null) {
webServer.stop();
}
throw ex;
}
}
refresh方法全貌:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//使用步骤检测应用程序标记启动。
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// 为刷新做准备,为当前的上下文记录状态,赋值等。
prepareRefresh();
// 保证获得一个新的工厂
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 为bean工厂的启动做准备
prepareBeanFactory(beanFactory);
try {
// 空方法,留给子类扩展,去修改工厂配置或新增bean定义都可
// 和BeanFactoryPostProcessor类似
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// 调用上下文中注册为BeanFactoryPostProcessors的bean
invokeBeanFactoryPostProcessors(beanFactory);
// 注册bean的的后置处理器用于拦截bean的创建。(扩展点)
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// 初始化MessageSource,用于国际化i18n
initMessageSource();
// 初始化EventMulticaster,用于广播事件
initApplicationEventMulticaster();
// 给子类预留的方法,子类可以独立实现,出事化一些特定的bean
onRefresh();
// 检测所有的listeners bean并注册
registerListeners();
// 完成bean工厂的实例化,初始化所有的非懒加载的单例bean
finishBeanFactoryInitialization(beanFactory);
// 完成刷新,并发布相应的事件
finishRefresh();
} catch (BeansException ex) {
// 销毁已经创建的单例以避免浪费资源。
destroyBeans();
// 重置'active'标志。
cancelRefresh(ex);
throw ex;
} finally {
// 重置Spring核心中的缓存,消除启动中所用的缓存资源,
// 因为我们已经不需要哪些单例bean的元数据了.
resetCommonCaches();
contextRefresh.end();
}
}
}
流程:
- prepareRefresh(为刷新做准备,记录当前的上下文状态,赋值等操作)
- 获得一个新的工厂方法,为bean工厂的启动做准备
- 添加扩展点 postProcessBeanFactory
- 调用上下文注册为beanFactoryPostProcess的bean
- 注册bean 的后置处理器用于拦截bean的创建
- 初试化messageSource初始化EventMulticaster,用于国际化和广播
- onRefresh 给子类预留的方法,子类可以单独实现
- 检测所有的listener bean 并注册
- 完成bean工厂的实例化,初始化所有非懒加载的单例bean
- 完成刷新,并发布相应的事件。
StartupStep是spring提供的步骤检测应用程序,核心容器及其基础结构组件可以使用ApplicationStartup在应用程序启动期间标记步骤,并收集关于执行上下文或其处理时间的数据,我们可以使用一个子类测试一下:
@Test
public void testApplicationStartup() {
BufferingApplicationStartup startup = new BufferingApplicationStartup(32);
StartupStep startupStep = startup.start("程序即将启动!");
startupStep.tag("第一步", "xxxx");
startupStep.tag("第二步", "xxxx");
startupStep.end();
StartupStep startupStep2 = startup.start("程序即将启动2!");
startupStep2.tag("第一步2", "xxxx");
startupStep2.tag("第二步2", "xxxx");
startupStep2.end();
}
通过debug我们发现,该组件将每一个步骤都在内存中保存了起来。当然,我们可以定制开发,将记录的步骤保存在任何地方
一,准备刷新阶段:
prepareRefresh(阶段)阶段
protected void prepareRefresh() {
// 记录了启动时间和容器当前状态(非关闭、活跃中)
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
// 初始化我们定义的PropertySource
//如果没有环境就创建一个环境,有就获得当前环境
initPropertySources();
// 验证所有标记为[必需]的属性都是[可解析]的
// 简单如:通过this.getProperty(key) == null判断存在的key是否有可用的value
getEnvironment().validateRequiredProperties();
// 初始化一些前置刷新的监听器,默认没有,子类可以实现
// 刷新容器【可以是从未启动到启动】,【也可以在启动中刷新】,当然像有的实现类只允许刷新一次
// 这本质上是将监听器初始化
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// 将本地应用程序监听器器重置为刷新前状态。
// 清空原有的,新增早期的必须的监听器
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// 允许早期ApplicationEvents的集合,一旦多播机可用就会发布…
this.earlyApplicationEvents = new LinkedHashSet<>();
}
1. initPropertySources
initPropertySources方法在抽象类中的默认实现为空,在GenericWebApplicationContext中,他将servlet上下文和spring上下文相关联,代码如下
@Override
protected void initPropertySources() {
// 获取环境对象,子类中可以有不同实现,web环境下就是ApplicationServletEnvironment
ConfigurableEnvironment env = getEnvironment();
// 此处判断是否是web环境
if (env instanceof ConfigurableWebEnvironment configurableWebEnv) {
// 开始初始化环境对象
configurableWebEnv.initPropertySources(this.servletContext, null);
}
}
@Override
public ConfigurableEnvironment getEnvironment() {
// 环境对象没有就直接创建一个,就是一个key->value集合
if (this.environment == null) {
this.environment = createEnvironment();
}
return this.environment;
}
public void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
WebApplicationContextUtils.initServletPropertySources(getPropertySources(), servletContext, servletConfig);
}
public static void initServletPropertySources(MutablePropertySources sources,@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
Assert.notNull(sources, "'propertySources' must not be null");
// 将ServletConfig和ServletContext保存在当前环境中
// 这样就可servlet容器建立了连接
// servletContextInitParams
String name = StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME;
if (servletContext != null && sources.get(name) instanceof StubPropertySource) {
sources.replace(name, new ServletContextPropertySource(name, servletContext));
}
// servletConfigInitParams
name = StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME;
if (servletConfig != null && sources.get(name) instanceof StubPropertySource) {
sources.replace(name, new ServletConfigPropertySource(name, servletConfig));
}
}
@Override
protected void initPropertySources() {
// 获取环境对象,子类中可以有不同实现,web环境下就是ApplicationServletEnvironment
ConfigurableEnvironment env = getEnvironment();
// 此处判断是否是web环境
if (env instanceof ConfigurableWebEnvironment configurableWebEnv) {
// 开始初始化环境对象
configurableWebEnv.initPropertySources(this.servletContext, null);
}
}
@Override
public ConfigurableEnvironment getEnvironment() {
// 环境对象没有就直接创建一个,就是一个key->value集合
if (this.environment == null) {
this.environment = createEnvironment();
}
return this.environment;
}
public void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
WebApplicationContextUtils.initServletPropertySources(getPropertySources(), servletContext, servletConfig);
}
public static void initServletPropertySources(MutablePropertySources sources,@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
Assert.notNull(sources, "'propertySources' must not be null");
// 将ServletConfig和ServletContext保存在当前环境中
// 这样就可servlet容器建立了连接
// servletContextInitParams
String name = StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME;
if (servletContext != null && sources.get(name) instanceof StubPropertySource) {
sources.replace(name, new ServletContextPropertySource(name, servletContext));
}
// servletConfigInitParams
name = StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME;
if (servletConfig != null && sources.get(name) instanceof StubPropertySource) {
sources.replace(name, new ServletConfigPropertySource(name, servletConfig));
}
}
- servletContextInitParams:ServletConfigPropertySource实例,保存servletContext实例。
- servletConfigInitParams:ServletConfigPropertySource实例,保存servletConfig实例。
这个方法是幂等的,它可以被调用很多次,但是它只会将最新传入的实例做替换,这两个实例存在于servlet环境中,这样实现可以将spring上下文和servlet上下文相关联,在spring中我们可以很容易获得这两个servlet实例,多个环境各司其职,职责分明,这是很好的体现:
2、环境校验
在默认情况下的校验规则之分简单,如下,仅仅查看有没有一些空值:
@Override
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;
}
}
2.生成一个新的工厂
obtainFreshBeanFactory()阶段
这个阶段会产生一个全新的无污染的beanFactory:
// 告诉子类刷新内部的bean工厂。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
其内部的核心方法如下,我们以GenericApplicationContext的实现为主:
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 刷新bean工厂,并将bean工厂返回
refreshBeanFactory();
return getBeanFactory();
}
三、为bean工厂启动做准备
此时,我们的工厂已经创建好了,但是目前依旧是一个新鲜的工厂,我们需要对其进行一些配置,为以后的工作做准备:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//ConfigurableBeanFactory接口的配置项
beanFactory.setBeanClassLoader(getClassLoader());
// BeanExpressionResolver接口的标准实现,使用Spring的表达式模块解析和计算Spring EL。
//包含其中的BeanFactory中的所有bean都可用为具有通用bean名称的预定义变量,
//包括标准上下文bean,如“environment”、“systemProperties”和“systemEnvironment”。
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.
addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// ConfigurableListableBeanFactory接口的配置项
// 忽略自动装配的给定依赖接口。
// 应用程序上下文通常使用它来注册以其他方式解析的依赖项,比如通过ApplicationContextAware解析ApplicationContext。
// 缺省情况下,只有BeanFactoryAware接口被忽略。若要忽略其他类型,请为每种类型调用此方法
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);
// 增加一个bean的后置处理器处理一些aware接口,就是上边哪些
// 也就意味着,以上那些bean是在实例化后被注入进去,而不是属性填充时
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 将以下内容注册为可以解析的依赖,可以使用@Autowire注入
// this也就是当前的上下文,它具有很多能力,我们注入这些接口时获得的实例就是上下文本身
// @Autowire
// BeanFactory beanFactory;
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 将早期的后处理器注册为applicationlistener,用于检测内部bean
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 检测一个LoadTimeWeaver是否存在,并准备织入
if (!NativeDetector.inNative./img() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// 为类型匹配设置一个临时的ClassLoader。
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// 注册默认环境bean。
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
// environment
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
// systemProperties
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
// systemEnvironment
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
// applicationStartup
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
}
1、ApplicationContextAwareProcessor
该类是一个bean的后置处理器,目的是在bean创建完成以后,主动调用一些aware接口。对实现了EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware和ApplicationContextAware接口的bean提供ApplicationContext、Environment或StringValueResolver等bean的注入。
2.ApplicationListenerDetector
class ApplicationListenerDetector implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor {
private static final Log logger = LogFactory.getLog(ApplicationListenerDetector.class);
private final transient AbstractApplicationContext applicationContext;
private final transient Map<String, Boolean> singletonNames = new ConcurrentHashMap<>(256);
public ApplicationListenerDetector(AbstractApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
// beanDefintion合并以后的回调,将实现了listener接口的bean名称全部保存
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if (ApplicationListener.class.isAssignableFrom(beanType)) {
this.singletonNames.put(beanName, beanDefinition.isSingleton());
}
}
// 初始化前的回调,不做任何的事情
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
// 初始化后的回调
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
// 这里告诉我们,监听器的注册
if (bean instanceof ApplicationListener<?> applicationListener) {
// 配合postProcessMergedBeanDefinition来共同探测listener
// todo://源码注解说getNamesByType的探测可能不够准确
Boolean flag = this.singletonNames.get(beanName);
if (Boolean.TRUE.equals(flag)) {
// 单例bean(顶层或内部):动态注册
this.applicationContext.addApplicationListener(applicationListener);
}
else if (Boolean.FALSE.equals(flag)) {
if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
// 实现了ApplicationListener接口,但是由于它没有单例作用域,所以不能通过它所包含的
//ApplicationContext来进行事件多播。只有顶级侦听器bean允许是非单例范围。
logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface but is not reachable for event multicasting by its containing ApplicationContext because it does not have singleton scope. Only top-level listener beans are allowed to be of non-singleton scope.");
}
this.singletonNames.remove(beanName);
}
}
return bean;
}
// 销毁前的回调,将注册的监听去全部移除
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) {
if (bean instanceof ApplicationListener<?> applicationListener) {
try {
ApplicationEventMulticaster multicaster = this.applicationContext.getApplicationEventMulticaster();
multicaster.removeApplicationListener(applicationListener);
multicaster.removeApplicationListenerBean(beanName);
}
catch (IllegalStateException ex) {
// ApplicationEventMulticaster not initialized yet - no need to remove a listener
}
}
}
}
3、registerResolvableDependency该方法是将一个bean注册为可以被解析的容器的bean。
四、对bean工厂的后置处理
postProcessBeanFactory(beanFactory)阶段
抽象父类方法中同样是一个空的方法,是留给其他子类扩展的地方
看一下在GenericWebApplicationContext中的实现,这就是典型的子类扩展:
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 如果是web环境,新增一个后置处理器,并忽略一个接口
if (this.servletContext != null) {
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
}
// 同时注册新的作用域,我们看到的request,session等作用域都在这里注册
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
// 此处注入servlet的上下文环境
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
}
再看下注册作域的实现如下:
public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory,@Nullable ServletContext sc) {
// 注册request,session,application作用域
beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope());
if (sc != null) {
ServletContextScope appScope = new ServletContextScope(sc);
beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);
sc.setAttribute(ServletContextScope.class.getName(), appScope);
}
// 注册可以被解析的依赖项的依赖关系
// @Autowire
// ServletRequest servletRequest;
beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory());
beanFactory.registerResolvableDependency(ServletResponse.class, new ResponseObjectFactory());
beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory());
beanFactory.registerResolvableDependency(WebRequest.class, new WebRequestObjectFactory());
if (jsfPresent) {
FacesDependencyRegistrar.registerFacesDependencies(beanFactory);
}
}
五、调用beanfactory的后置处理器
invokeBeanFactoryPostProcessors(beanFactory)阶段
这是留给应用程序的扩展点,我们自行编写或第三方扩展的beanFactoryPostProcessor会在这里被调用:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 参数一:当前的bean工厂
// 参数二:已经注册的BeanFactoryPostProcessors,可能是子类注册的或者之前的扩展点注册
// 该方法是核心的调用点,会从beanDefinition中寻找所有的BeanFactoryPostProcessor调用
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// 检测LoadTimeWeaver并准备编织,这个实现需要使用spring探针,是加载时织入实现代理
// 因为此时,bean工厂已经准备就绪,接着就是加载并实例化bean了
// aspectj生成代理的织入时机有三个,编译时、加载时、运行时,自己可以找博客看
// 该处的内容我们暂时不看
if (!NativeDetector.inNative./img() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
其中getBeanFactoryPostProcessors方法十分简单如下:
成员变量beanFactoryPostProcessors在之前的准备过程中,由核心准备工作,子类扩展等形式返回准备好的后置处理器:
public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
return this.beanFactoryPostProcessors;
}
成员变量的beanFactoryPostProcessors可以通过编程的方式添加,请看如下的测试用例:
@Test
public void testAddBeanFactoryPostProcessor(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.scan("com.ydlclass");
applicationContext.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
applicationContext.refresh();
}
在该方法中主要调用的后置处理器分为两类,如下:
- BeanDefinitionRegistryPostProcessor,他是BeanFactoryPostProcessor的子接口,给我们一个机会可以再注册更多的beanDefinition。
- BeanFactoryPostProcessor,给我们一个机会对目前的bean工厂做更多额外的配置。
1、注册器后置处理
该方法中,我们会首先处理这一类后置处理器,其本是也是BeanFactoryPostProcessor,结构如下:
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
在这一类处理器中,我们可以获取一个BeanDefinitionRegistry,额外获得一个注册bean的机会。
2、bean工厂的后置处理器
该接口只有一个回调函数postProcessBeanFactory,他给我传入当前已经创建好的bean工厂,给我们一个机会可以做一些额外的配置:
@FunctionalInterface
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
3、处理过程
后置处理器大致分类:
- 编程方式直接加入的,可能是准备阶段的任意地方,包括子类扩展,此处理器可以直接调用,已经实例化完毕,这是第二个参数
addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
2.我们定义的后置处理器,此时仅仅处于BeanDefinition阶段,尚未实例化,无法直接调用,这样是传递第一个参数的原因
3.对于后置处理器spring还细化出一个新的后置处理器BeanDefinitionRegistryPostProcessor,他是BeanFactoryPostProcessor的子接口,给我们一个机会再继续注册一些beanDefinition。
4.对于后置处理器spring都提供了优先级接口(PriorityOrdered)和可排序(Ordered)接口,为后置处理器提供了顺序执行的机制。
// AbstractApplicationContext对BeanFactoryPostProcessor的委托处理类
final class PostProcessorRegistrationDelegate {
// 工具类,负责调佣BeanFactoryPostProcessors
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// 存放已经处理过的bean
Set<String> processedBeans = new HashSet<>();
//----------------------------------------------------
// 第一类后置处理器,这一类是BeanDefinitionRegistryPostProcessor
// 他们的优先级次之,在这个后置处理器中可能还会注册其他的bean
//---------------------------------------------------
// 如果传入的beanFactory实现了BeanDefinitionRegistry接口
// spring还提供了BeanDefinitionRegistryPostProcessor的扩展点
if (beanFactory instanceof BeanDefinitionRegistry registry) {
// 存放BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
// 存放BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 这里是处理参数中传递的beanFactoryPostProcessors
// 进行归类
// 一类是BeanDefinitionRegistryPostProcessor
// 一类是BeanFactoryPostProcessor
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor registryProcessor) {
// 直接调用了
// BeanDefinitionRegistryPostProcessor他有两个回调
// 此处调用了第一个会传入一个注册器,给我们机会注册更多bean定义
registryProcessor.postProcessBeanDefinitionRegistry(registry);
// 放有注册器的后置处理器
registryProcessors.add(registryProcessor);
} else {
// 放常规的后置处理器
regularPostProcessors.add(postProcessor);
}
}
// 这里定义了当前注册的bean
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// PriorityOrdered(优先级要求)--------------------------------------------------
// 首先,调用实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessors。
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 匹配实现了PriorityOrdered接口的beandefinition
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 此处调用getbean就是实例化bean
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
// 同时把他加入处理过的bean当中
processedBeans.add(ppName);
}
}
// 对这些bean进行排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 这个集合专门存放BeanDefinitionRegistryPostProcessor
registryProcessors.addAll(currentRegistryProcessors);
// postProcessBeanDefinitionRegistry方法调用
// 这里可能会注入一些其他的bean
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
// 调用完了清理,下个阶段复用
currentRegistryProcessors.clear();
// Ordered(有序的)---------------------------------------------------------------
// 接下来,调用实现Ordered的BeanDefinitionRegistryPostProcessors。
// ...中间省略了实现order接口的实现,和PriorityOrdered一模一样
// 没有实现Ordered和PriorityOrdered接口的其他的beandefinitionregistrypostprocessor-----
// ...中间省略了实现其他beandefinitionregistrypostprocessor的方法,内容大致一样
// 现在,调用到目前为止处理的所有处理器的postProcessBeanFactory回调。
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// 调用与上下文注册的工厂处理器。
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
//------------------------------------------------------
// 第二类:普通的后置处理器,普通的实现了BeanFactoryPostProcessor的beanDefinition
//------------------------------------------------------
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// 在实现PriorityOrdered、Ordered和其他的BeanFactoryPostProcessors之间进行分离。
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// 跳过-已经在上面的第一阶段处理
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// priorityOrderedPostProcessors优先实例化了
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 首先,调用实现PriorityOrdered的BeanFactoryPostProcessors。
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 接下来,调用实现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);
// 最后,调用所有其他beanfactorypostprocessor。
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// 清除缓存的合并bean定义,因为后处理器可能有修改原始元数据,例如替换值中的占位符…
beanFactory.clearMetadataCache();
}
// ----其他方法略去
}
先后顺序是:
- 实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
- 实现了Ordered接口的BeanDefinitionRegistryPostProcessor
- 其他普通的BeanDefinitionRegistryPostProcessor
- 实现了PriorityOrdered接口的BeanFactoryPostProcessor
- 实现了Ordered接口的BeanFactoryPostProcessor
- 其他普通的BeanFactoryPostProcessor
6.注册bean的后置处理器
registerBeanPostProcessors(beanFactory)阶段方法如下:
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
核心代码如下:
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// 获取所有实现了BeanPostProcessor接口的bean的名字
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// 记录BeanPostProcessor数量
// getBeanPostProcessorCount()编程的方式add进去的
// 1 BeanPostProcessorChecker
// postProcessorNames.length容器内没有初始化的
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
// 注册BeanPostProcessorChecker,
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// 有优先级要求的,实现了priorityOrdered接口
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
// 内部的BeanPostProcessor
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
// 有顺序要求的,实现了Ordered接口
List<String> orderedPostProcessorNames = new ArrayList<>();
// 没有顺序要求的
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);
// MergedBeanDefinitionPostProcessor也是一个后置处理器
// 我们稍后看
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 首先,注册实现PriorityOrdered的BeanPostProcessors。
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// 接下来,实例化并注册实现Ordered接口的BeanPostProcessors。
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);
// 现在,实例化并注册其他的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);
// 最后,注册所有的MergedBeanDefinitionPostProcessor
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// ApplicationListener探测器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
主要就是如下四个list
// 有优先级要求的,实现了priorityOrdered接口
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
// 内部的BeanPostProcessor
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
// 有顺序要求的,实现了Ordered接口
List<String> orderedPostProcessorNames = new ArrayList<>();
// 没有顺序要求的
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
priorityOrderedPostProcessors ,orderedPostProcessors,nonOrderedPostProces 内部可能包含内部的BeanPostProcessor(查看是不是MergedBeanDefinitionPostProcessor)所以要筛选并放入 internalPostProcessors列表中。
1.合并beanDefinition
MergedBeanDefinition是spring获取bean流程中一个重要的处理过程,他将基础的bean处理成新的BeanDifinition对象,也就是RootBeanDefinition,后续的处理过程都依赖于这个对象。
在spring内部实际使用的BeanDefinition其实都是合并之后的RootBeanDefinition对象,通过他进行对象的实例化,注入等操作。spring同样为这个关键接待您提供了一个可供后续操作并后RootBeanDefinition的扩展点(后置处理器),通过这个扩展点,可以实现对RootBeanDefinition的操作。
和前面的beanDefinitionRegistryPostProcessor对比
扩展点 | 用途 |
BeanDefinitionRegistryPostProcessor | 可以注册或者更改原始的BeanDefinition |
MergedBeanDefinitionPostProcessor | 可以修改RootDefinition |
具体整合过程,从传入的beanFactory中获取全部的实现了BeanPostProcess接口的bean的名字。然后不断循环分组,分成实现了priorityOrdered的,实现了Orderd接口的,包括内部的BeanPostProcessor以及没有顺序要求的。。。等等。注意internalPostProcessors 里面放入的是符合MergedBeanDefinitionPostProcessor的后置处理器。在循环分组结束之后,注册实现PriorityOrdered的BeanPostProcessor,然后是实现Ordered接口的BeanPostProcessors,再次是实例化并注册其他的BeanPostProcessors(nonOrderedPostProcessors)。最后注册所有的MergedBeanDefinitionPostProcessor
注册语句:
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
2、监听器探测器
检测实现了ApplicationListener接口的bean的BeanPostProcessor。这将捕获getBeanNamesForType和仅针对顶级bean的相关操作不能可靠地检测到的bean。
class ApplicationListenerDetector implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor {
private static final Log logger = LogFactory.getLog(ApplicationListenerDetector.class);
private final transient AbstractApplicationContext applicationContext;
private final transient Map<String, Boolean> singletonNames = new ConcurrentHashMap<>(256);
public ApplicationListenerDetector(AbstractApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
// 合并bean的定义前
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if (ApplicationListener.class.isAssignableFrom(beanType)) {
this.singletonNames.put(beanName, beanDefinition.isSingleton());
}
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
// BeanPostProcessor的回调
// 这里说明spring中的listener必须是单例的才能生效
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof ApplicationListener<?> applicationListener) {
// 判断是不是单例
Boolean flag = this.singletonNames.get(beanName);
if (Boolean.TRUE.equals(flag)) {
// 单例bean(顶层或内部):动态注册
this.applicationContext.addApplicationListener(applicationListener);
}
else if (Boolean.FALSE.equals(flag)) {
if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
// inner bean with other scope - can't reliably process events
logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface but is not reachable for event multicasting by its containing ApplicationContext because it does not have singleton scope. Only top-level listener beans are allowed to be of non-singleton scope.");
}
this.singletonNames.remove(beanName);
}
}
return bean;
}
// 一个bean在销毁前的回调,从多播器中移除
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) {
if (bean instanceof ApplicationListener<?> applicationListener) {
try {
ApplicationEventMulticaster multicaster = this.applicationContext.getApplicationEventMulticaster();
multicaster.removeApplicationListener(applicationListener);
multicaster.removeApplicationListenerBean(beanName);
}
catch (IllegalStateException ex) {
// ApplicationEventMulticaster not initialized yet - no need to remove a listener
}
}
}
}
七、初始化MessageSource
initMessageSource()阶段
容器启动时,如果容器中不存在对应的Bean实例,则容器中默认创建一个DelegatingMessageSource的实例来实现国际化。DelegatingMessageSource实现的具体功能需要向上委托,否则降级处理(处理成默认字符串或者抛出异常):
public String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale) {
if (this.parentMessageSource != null) {
return this.parentMessageSource.getMessage(code, args, defaultMessage, locale);
}
else if (defaultMessage != null) {
return renderDefaultMessage(defaultMessage, args, locale);
}
else {
return null;
}
}
SpringBoot中使用【ResourceBundleMessageSource】 的实现,SpringBoot默认的自动装配的 MessageSource即就是 ResourceBundleMessageSource:
配置文件:
spring:
messages:
basename: i18n/messages
encoding: UTF-8
在springboot或spring中,只需要注入这个bean直接使用即可
@Autowired
MessageSource messageSource;
八、初始化多播器
initApplicationEventMulticaster()阶段
向容器注入一个多播器实例,默认为SimpleApplicationEventMulticaster的实现:
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 {
// 默认使用SimpleApplicationEventMulticaster进行广播事件,注册listener
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() + "]");
}
}
}
九、onRefresh()
该方法在抽象类中也是空的,同样是留给子类进行扩展使用,此时一切的基本工作都已经准备好了:
web环境下在此阶段会创建一个服务器:
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
StartupStep createWebServer = getApplicationStartup().start("spring.boot.webserver.create");
ServletWebServerFactory factory = getWebServerFactory();
createWebServer.tag("factory", factory.getClass().toString());
this.webServer = factory.getWebServer(getSelfInitializer());
createWebServer.end();
getBeanFactory().registerSingleton("webServerGracefulShutdown",
new WebServerGracefulShutdownLifecycle(this.webServer));
getBeanFactory().registerSingleton("webServerStartStop",
new WebServerStartStopLifecycle(this, this.webServer));
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context", ex);
}
}
initPropertySources();
}
十、注册监听器
registerListeners()阶段
protected void registerListeners() {
// 首先注册静态指定的侦听器。比如用编程的方式加入:
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 获得bean的名字
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
// 只需要加入名字即可,不要实例化,可以让容器去实例化,我们发布事件时会筛选和缓存
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// 发布早期应用程序事件,一般也没有,也是可以拓展的
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
#十一、完成bean工厂的初始化
finishBeanFactoryInitialization(beanFactory)阶段
此方法非常复杂,我们独立一个章节讲解,在这里会完成所有的单例bean的创建过程。
十二、完成刷新
protected void finishRefresh() {
// 清除上下文级资源缓存(例如扫描ASM元数据)。
clearResourceCaches();
// 初始化一个生命周期处理器,并标志为running状态;
initLifecycleProcessor();
getLifecycleProcessor().onRefresh();
// 发布最终事件。
publishEvent(new ContextRefreshedEvent(this));
}
上边的内容告诉我们,我们可以订阅ContextRefreshedEvent事件,在容器启动后完成一些初始化操作。
十三、恢复现场
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 销毁已经创建的单例以避免悬空资源。
destroyBeans();
// 重置'active'标志。
cancelRefresh(ex);
// 向调用者传播异常。
throw ex;
}
finally {
// 重置Spring核心中的公共内省缓存,因为我们可能再也不需要单例bean的元数据了……
resetCommonCaches();
contextRefresh.end();
}