前面的梳理中已经将Spring的容器的创建、Bean的创建、BeanPostProcessor的使用、ApplicationListener的使用、代理模式梳理完成,其实以上的所有的梳理都是Spring的Bean声明周期的细节,现在从整体上分析一下Spring中Bean声明周期是如何实现的。
以下的分析会从容器的启动、注解如何加载Bean、创建BeanDefinition、容器的刷新(核心)、创建Bean、销毁Bean的链路梳理,从源头了解Bean的生命周期。
容器启动流程
容器启动流程就是我们平时使用SpringBoot的启动类,在启动类中都会有一段SpringApplication.run(DispatchAdapterApplication.class, args) 代码,这段代码就是启动Spring服务的调用。在这段代码中启动了Spring应用,那么其中又是如何启动Spring容器,并且启动过程中如何将Bean注入到容器中的呢?从源码中梳理整个过程。
容器启动流程:
- 创建应用上下文接口ConfigurableApplicationContext,该接口可以理解为是最顶级的接口,该接口中提供了设置Spring环境、设置BeanFactoryPostProcessor、ApplicationListener、注册Bean、销毁Bean的所有方法,该接口是提供给应用启动程序使用,并且主要使用在启动和关闭阶段。
//Spring启动实现类
public class SpringApplication {
//注解的方式注入类的实现
public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context."
+ "annotation.AnnotationConfigApplicationContext";
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
//创建AnnotationConfigApplicationContext实现类
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//对AnnotationConfigApplicationContext的准备逻辑,设置环境、监听器等
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//调用容器刷新逻辑
refreshContext(context);
//刷新之后的处理,开发者可以重写该方法做后续的处理
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
.....
return context;
}
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
//默认会调用这个实例化AnnotationConfigApplicationContext
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
......
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
private void refreshContext(ConfigurableApplicationContext context) {
//调用刷新逻辑
refresh(context);
if (this.registerShutdownHook) {
try {
//关闭容器的钩子函数,关闭容器的逻辑中封装了对销毁bean,关闭事件订阅、关闭beanFactory的逻辑
//我们一般做服务的优雅上下线就是通过这个钩子函数做的处理
context.registerShutdownHook();
}
.......
}
}
}
注解配置类注册流程
- 配置应用上下文实现类AnnotationConfigApplicationContext,该类是ConfigurableApplicationContext默认的实现类,从字面意思也可以看到这是一个注解配置的应用上下文实现类,该类可以理解为会扫描所有带**@Configuration** 和**@Component **将带有这些注解的类注入到容器中。
- 注解配置应用上下文实现类中会执行scan和register两个逻辑,scan负责扫描所有带有注解的Bean、register负责将这些类解析为BeanDefinition注入到容器中。
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
private final AnnotatedBeanDefinitionReader reader;
private final ClassPathBeanDefinitionScanner scanner;
//构造函数初始化两个BeanDefinitionReader,分别为AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner
//分别对应使用注解的加载BeanDefinition和使用xms的加载BeanDefinition
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
//功能同上,只不过该构造函数指定了BeanFactory
public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
super(beanFactory);
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
//初始化自己
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
//将注解的bean解析到容器中的beanDefinition,所有的bean被初始化为BeanDefinition
register(annotatedClasses);
//执行容器的刷新逻辑
refresh();
}
public AnnotationConfigApplicationContext(String... basePackages) {
this();
//通过路径扫描所有的bean,然后将bean解析到容器中的beanDefinition
scan(basePackages);
//执行容器的刷新逻辑
refresh();
}
}
注册BeanDefinition流程
- 在AnnotationConfigApplicationContext实现类中register的逻辑就是注册BeanDefinition,将Bean解析为BeanDefinition注册到容器中,用于后续的Bean的创建。
- 具体BeanDefinition的创建注入是在DefaultListableBeanFactory中实现的,该实现在BeanDefinition那篇中具体说过。
public class AnnotatedBeanDefinitionReader {
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(instanceSupplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
customizer.customize(abd);
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
......
else {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
//将BeanDefinition写入到BeanDefinition的容器
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
......
}
}
容器刷新流程
- BeanDefinition完成注入之后,那么后续就可以提供给容器使用,但是在容器刷新逻辑中还需要完成一些必要的事情,比如BeanPostProcessor、BeanFactoryPostProcessor、ApplicationListener等。开发者定义的这些接口的实现类就是在容器刷新这层实现注入的。
- 以BeanPostProcessor为例,开发者实现该接口的实现类,会在该逻辑中注入到指定的ProcessorList中,后续Bean创建时则会遍历ProcessorList执行指定Bean的before和after的增强处理。
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 刷新前的处理,比如初始化applicationListeners,初始化配置数据等
prepareRefresh();
// 获取前面初始化的beanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 准备beanFactory,向容器中注册一些配置数据,比如ClassLoader、BeanExpressionResolver
//BeanPostProcessor等等
prepareBeanFactory(beanFactory);
try {
//允许子类通过该方法对beanFactory做进一步增强
postProcessBeanFactory(beanFactory);
// 执行beanFactoryPostProcessor的前置和后置处理,类似beanPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// 将实现BeanPostProcessor的增强注册到beanFactory的相关列表中,用于后续执行bean的前置和后置处理逻辑
registerBeanPostProcessors(beanFactory);
// 初始化 MessageSource,可以做国际化的处理
initMessageSource();
// 初始化事件分发器,用于后续的的ApplicationEvent的分发
initApplicationEventMulticaster();
// 初始化一些特殊的子类,如果子类重写了该方法,那么在初始化时会执行重写该方法的子类逻辑,
//可以理解为做增强处理
onRefresh();
// 使用前面初始化的事件分发器,将监听者注册到分发器,用于后续的消息监听
registerListeners();
// 初始化所有的单例bean(非懒加载的)
finishBeanFactoryInitialization(beanFactory);
// 完成容器刷新,可以将前面注册的事件通过事件分发器发布事件
finishRefresh();
}catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 销毁bean的实现
destroyBeans();
// 取消刷新,修改容器状态
cancelRefresh(ex);
throw ex;
} finally {
resetCommonCaches();
}
}
}
}
创建Bean的流程
- 前面所有的准备工作完成之后,那么后续就可以执行Bean的创建,创建Bean的过程中依赖的BeanDefinition、BeanPostProcessor、ApplicationListener等在前面已经完成准备工作,在此时需要实现调用即可。所以前面大部分工作都是为了创建Bean做准备。
- 具体的实现如源码所示
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
else {
.......省略部分代码
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 处理bean的依赖问题,比如循环依赖
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 判断BeanDefinition是否是单例
if (mbd.isSingleton()) {
//获取单例Bean
sharedInstance = getSingleton(beanName, () -> {
try {
//创建Bean
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
//如果出现异常则销毁Bean
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
.......
return (T) bean;
}
}
销毁Bean的流程
- 既然创建了Bean,那么也要对Bean进行销毁,不然Bean一直占用堆内存也会造成影响,因此当服务关闭时在registerShutdownHook中实现了销毁Bean的逻辑。
- 在了解Bean在容器中的表现形式之后,知道Bean其实是put到一个map容器中,那么销毁Bean自然而然就是将map中的数据进行remove,有了这个想法,再看源码就会顺利很多。
- 追本溯源之后可以看到销毁Bean的最终调用就是将singletonObjects(一级缓存)、singletonFactories(三级缓存)、earlySingletonObjects(二级缓存)、registeredSingletons(缓存BeanName的容器)四个容器中的数据进行remove。所以销毁Bean的逻辑只要了解了Bean的创建,那么销毁自然可以推测出来。
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
@Override
public void registerShutdownHook() {
if (this.shutdownHook == null) {
// No shutdown hook registered yet.
this.shutdownHook = new Thread() {
@Override
public void run() {
synchronized (startupShutdownMonitor) {
doClose();
}
}
};
Runtime.getRuntime().addShutdownHook(this.shutdownHook);
}
}
protected void destroyBeans() {
getBeanFactory().destroySingletons();
}
}
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
//销毁Bean
public void destroySingletons() {
if (logger.isTraceEnabled()) {
logger.trace("Destroying singletons in " + this);
}
synchronized (this.singletonObjects) {
this.singletonsCurrentlyInDestruction = true;
}
String[] disposableBeanNames;
synchronized (this.disposableBeans) {
disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
}
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
destroySingleton(disposableBeanNames[i]);
}
this.containedBeanMap.clear();
this.dependentBeanMap.clear();
this.dependenciesForBeanMap.clear();
clearSingletonCache();
}
public void destroySingleton(String beanName) {
// Remove a registered singleton of the given name, if any.
removeSingleton(beanName);
// Destroy the corresponding DisposableBean instance.
DisposableBean disposableBean;
synchronized (this.disposableBeans) {
disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
}
destroyBean(beanName, disposableBean);
}
//清除容器中的Bean
protected void removeSingleton(String beanName) {
synchronized (this.singletonObjects) {
this.singletonObjects.remove(beanName);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.remove(beanName);
}
}
}
总结
从服务的启动到服务的关闭整个流程下来梳理了Bean的整个生命周期,根据这个生命周期自己可以根据这个流程对Spring中容器的实现和Bean的注入流程有了更深的了解,更多细节的部分可以根据一下的源码流程进行debug,毕竟debug看源码是最快的,debug的方式可以知道在每一步入参和出参的结果,以及每一步的正向流程。
- org.springframework.boot.SpringApplication#run(java.lang.String...)
- org.springframework.boot.SpringApplication#createApplicationContext
- org.springframework.context.annotation.AnnotationConfigApplicationContext#AnnotationConfigApplicationContext
- org.springframework.context.annotation.AnnotationConfigApplicationContext#register
- org.springframework.context.annotation.AnnotatedBeanDefinitionReader#registerBean
- org.springframework.context.annotation.AnnotatedBeanDefinitionReader#doRegisterBean
- org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerBeanDefinition
- org.springframework.context.support.AbstractApplicationContext#refresh
- org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization
- org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
- org.springframework.beans.factory.support.AbstractBeanFactory#getMergedLocalBeanDefinition
- org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
以上就是自己关于Spring中ApplicationListener的理解,个人能力有限,如有错误,欢迎评论私信指正!共同进步!