浅析Spring系列
浅析Spring启动流程(源码分析)
在Spring的启动上,主要以xxxApplicationContext作为启动类,本文将以当前流程的AnnotationConfigApplicationContext为例,浅析一下Spring的启动流程。正常使用Spring启动代码如下:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(xxx.class); //配置类
//context.scan(""); //扫描路径
context.refresh();
首先AnnotationConfigApplicationContext内部会有AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner两个实例,这两个类的作用为读取Bean的配置。本质上都是讲Bean解析成BeanDefinition,然后注册到IOC容器中(DefaultListableBeanFactory),等待被调用。
在实例化AnnotatedBeanDefinitionReader时,会注册BeanFactoryPostProcessor到IOC容器
- ConfigurationClassPostProcessor:处理@Configuration注解。
还会注册几个重要的BeanPostProcessor到IOC容器中:
- AutowiredAnnotationBeanPostProcessor:处理@Value、@Autowired注解。
- CommonAnnotationBeanPostProcessor:主要处理@PostConstruct、@PreDestroy注解。
启动流程代码如下,主要有几个步骤:
- 准备阶段
- BeanFactory处理
- BeanFactoryPostProcessor处理
- BeanPostProcessor处理
- 事件处理
- 实例化非延迟Bean
- 结束启动
//AbstractApplicationContext#refresh
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
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.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
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();
} finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
1.准备阶段
主要是状态记录、数据存储准备
//AbstractApplicationContext#prepareRefresh
protected void prepareRefresh() {
// Switch to active.
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
// 模版方法
initPropertySources();
// 属性校验
getEnvironment().validateRequiredProperties();
// 存储事件监听相关内容
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<>();
}
2.BeanFactory处理
BeanFactory为Spring的底层IOC容器
2.1获取BeanFactory
AnnotationConfigApplicationContext继承GenericApplicationContext,在默认构造下,GenericApplicationContext会创建一个BeanFactory,new一个DefaultListableBeanFactory实例。
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
obtainFreshBeanFactory方法,默认情况下会返回DefaultListableBeanFactory
//AbstractApplicationContext#obtainFreshBeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
//GenericApplicationContext#getBeanFactory
public final ConfigurableListableBeanFactory getBeanFactory() {
return this.beanFactory;
}
2.2设置BeanFactory
- 设置ClassLoader
- 设置expresess解析器
- 设置资源类型字段转换,在初始化阶段,将属性转换成所需的类型。
//AbstractApplicationContext#prepareBeanFactory
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
}
添加ApplicationContextAwareProcessor,该BeanPostProcessor主要处理各种Aware接口回调。
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
定义一些接口,无法被依赖查找、依赖注入
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.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
最后定义了几个环境变量相关的Bean
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());
}
2.3处理BeanFactory
实际是个模版方法,有需要的子类实现该方法即可
//AbstractApplicationContext#postProcessBeanFactory
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}
3.BeanFactoryPostProcessor处理
内部实际会通过静态方法调用
//AbstractApplicationContext#invokeBeanFactoryPostProcessors
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
}
内部有两个逻辑
3.1.处理BeanDefinitionRegistryPostProcessor接口
先处理BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor接口
按照以下顺序处理BeanDefinitionRegistryPostProcessor接口
- 实现了PriorityOrdered接口
- 实现了Order接口
- 其他
处理逻辑为:先进行排序(可能有多个接口实现),然后调用BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry接口。
等以上BeanDefinitionRegistryPostProcessor逻辑都处理完之后,再调用BeanFactoryPostProcessor的postProcessBeanFactory方法。
3.2.处理BeanFactoryPostProcessor接口
整体上也BeanDefinitionRegistryPostProcessor类似,也是通过以下顺序处理BeanFactoryPostProcessor接口
- 实现了PriorityOrdered接口
- 实现了Order接口
- 其他
处理逻辑为:先进行排序(可能有多个接口实现),然后调用BeanFactoryPostProcessor的postProcessBeanFactory方法。
当然,因为BeanDefinitionRegistryPostProcessor为BeanFactoryPostProcessor的子接口,在实现的时候有去重,不会出现重复调用postProcessBeanFactory方法。
默认情况下:会有2个内置的BeanFactoryPostProcessor接口,就是在AnnotatedBeanDefinitionReader构造器时添加
- ConfigurationClassPostProcessor
- EventListenerMethodProcessor
4.BeanPostProcessor处理
BeanPostProcessor处理通过调用静态方法处理,不过从方法名可以看出,这里的逻辑主要是注册BeanPostProcessor到BeanFactory为主。而BeanPostProcessor的逻辑会贯穿到Bean的生命周期中,可以基于此对Bean进行扩展。
//AbstractApplicationContext#registerBeanPostProcessors
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
4.1 BeanPostProcessorChecker
在处理注册逻辑之前,会添加一个BeanPostProcessorChecker到BeanFactory,这个作用是什么呢?
//PostProcessorRegistrationDelegate#registerBeanPostProcessors
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
}
BeanPostProcessorChecker的作用,主要是防止bean在所有的BeanPostProcessor注册到BeanFactory之前,就进行了实例化。
假设有个BeanPostProcessor 实现类,在内部依赖的其他的Bean,这样就会导致这个Bean在注册到BeanFactory过程中被创建(因为注册到BeanFactory之前,BeanPostProcessor 会先被实例化),这样就出触发BeanPostProcessorChecker逻辑
@Order
public class MyBeanPostProcessor implements BeanPostProcessor {
@Autowired
@Qualifier("createStr")
private String test;
@PostConstruct
public void init(){
System.out.println("MyBeanPostProcessor reference string : " + test);
}
}
BeanPostProcessorChecker逻辑也很简单,本身就是一个BeanPostProcessor接口,在postProcessAfterInitialization方法上做拦截,如果bean不是BeanPostProcessor或者不是Spring内部类的情况下,此时BeanFatory的BeanPostProcessor数量小于期望数量,那就打日志警告。在进行注册前,已经获取了所有的BeanPostProcessor数量,但此时注册逻辑可能还没走完,所以数量可能出现不一致。通过这种方式进行检测
//BeanPostProcessorChecker#postProcessAfterInitialization
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (!(bean instanceof BeanPostProcessor) && !isInfrastructureBean(beanName) &&
this.beanFactory.getBeanPostProcessorCount() < this.beanPostProcessorTargetCount) {
if (logger.isInfoEnabled()) {
logger.info("Bean '" + beanName + "' of type [" + bean.getClass().getName() +
"] is not eligible for getting processed by all BeanPostProcessors " +
"(for example: not eligible for auto-proxying)");
}
}
return bean;
}
4.2 注册逻辑
注册逻辑也很简单,通过顺序处理BeanPostProcessor接口,注意,这个过程中BeanPostProcessor会进行实例化和初始化。
- 实现了PriorityOrdered接口
- 实现了Order接口
- 其他
处理逻辑为:向BeanFactory添加BeanPostProcessor接口。
MergedBeanDefinitionPostProcessor接口(BeanPostProcessor的子接口)会最后添加到BeanFactory,最后在添加ApplicationListenerDetector(BeanPostProcessor接口的实现类)实例到BeanFactory中。
BeanFactory添加BeanPostProcessor逻辑:主要是维护在内部的List中
//AbstractBeanFactory#addBeanPostProcessor
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
// Remove from old position, if any
this.beanPostProcessors.remove(beanPostProcessor);
// Track whether it is instantiation/destruction aware
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true;
}
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
this.hasDestructionAwareBeanPostProcessors = true;
}
// Add to end of list
this.beanPostProcessors.add(beanPostProcessor);
}
5.事件处理
5.1ApplicationEventMulticaster创建
如果没有这个类的话,就会创建默认的SimpleApplicationEventMulticaster用于事件发布等逻辑。Spring事件相关的处理,在ApplicationContext有统一的入口,但内部处理逻辑都是ApplicationEventMulticaster在处理。
//AbstractApplicationContext#initApplicationEventMulticaster
protected void initApplicationEventMulticaster() {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
}
5.2ApplicationListener注册
- 获取ApplicationListener,然后添加到ApplicationEventMulticaster中。
- 如果有早期的事件,那么也将通过ApplicationEventMulticaster进行发布。那么为什么会有早期事件?
//AbstractApplicationContext#registerListeners
protected void registerListeners() {
// Register statically specified listeners first.
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 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);
}
// Publish early application events now that we finally have a multicaster...
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
为什么会有早期事件?从事件发布来说,其实一般都会使用到ApplicationContext的实现类进行处理,一般来说,会处理到AbstractApplicationContext的publishEvent方法上。而实际上在ApplicationEventMulticaster还没被处理之前,就可有可能会进行事件发布,但此时ApplicationEventMulticaster还没有被处理,可能先记录下来,等ApplicationEventMulticaster添加后再进行处理。
这里会判断earlyApplicationEvents 是否为null,在prepareRefresh方法时会设置为为List;在registerListeners时又会设置为null。
//AbstractApplicationContext#publishEvent
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
// Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// Publish event via parent context as well...
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
6.实例化非延迟Bean
此步骤的逻辑在AbstractApplicationContext的finishBeanFactoryInitialization方法中,调用BeanFactory的preInstantiateSingletons方法,对非延迟Bean进行实例化
//AbstractApplicationContext#finishBeanFactoryInitialization
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
beanFactory.preInstantiateSingletons();
}
实例化有几个逻辑:
- 找需要实例化的bean:非抽象、单例、不用延迟实例化
- 对于FactoryBean来说(通过FactoryBean接口包装了Bean的实例化,可以用于复杂Bean的创建),会判断是否是SmartFactoryBean接口,并且isEagerInit方法为true(默认为false),则会对实际的Bean进行实例化。
- 对于实现了SmartInitializingSingleton接口的Bean来说,还会调用afterSingletonsInstantiated方法
//DefaultListableBeanFactory#preInstantiateSingletons
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.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
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 {
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
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();
}
}
}
}
7.结束启动
- 会清空资源缓存。
- 初始化LifecycleProcessor处理器
- LifecycleProcessor启动。会对SmartLifecycle中要求isAutoStartup方法的Lifecycle接口进行调用,start接口。(作用:Lifecycle接口用于实现bean的生命周期)
- 发布ContextRefreshedEvent事件
代码如下
//AbstractApplicationContext#finishRefresh
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);
}
无论启动成功还是失败,最后都会调用resetCommonCaches进行清理过程中产生的缓存数据。
//AbstractApplicationContext#resetCommonCaches
protected void resetCommonCaches() {
ReflectionUtils.clearCache();
AnnotationUtils.clearCache();
ResolvableType.clearCache();
CachedIntrospectionResults.clearClassLoader(getClassLoader());
}