用于源码分析的代码:Github 接着上一篇继续debug。上一篇已经将源码4.3的逻辑分析完了,这一篇从源码4.5处继续:
public ConfigurableApplicationContext run(String... args) {
//StopWatch就是一个监控程序启动时间的类,start方法表示开始计时,stop方法表示计时结束
//用于日志输出启动时间
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
// 设置一个环境变量,该环节变量标识当前程序是在没有显示器、鼠标等显示设备上运行的
// 目的是为了能直接访问支持在无显示设备下的图形和文字处理对象的API,比如AWT的绘图API
configureHeadlessProperty();
// 1.0
SpringApplicationRunListeners listeners = getRunListeners(args);
// 2.0
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 3.0
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
// 4.0
configureIgnoreBeanInfo(environment);
// 4.1
Banner printedBanner = printBanner(environment);
// 4.2
context = createApplicationContext();
// 4.3
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 4.4
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 4.5
refreshContext(context);
// 空方法,没有内容
afterRefresh(context, applicationArguments);
// 计算整个启动过程的耗时
stopWatch.stop();
// 输出耗时等日志
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
// 发布context的started事件
listeners.started(context);
// 4.6 将启动行的参数传给容器内的ApplicationRunner和CommandLineRunner两个接口的实现类,调用他们的run方法,spring默认是没有配置的,可以自定义扩展类,详见后面的4.6的debug截图
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
// 发布context的running事件
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
还是首先列出自己的问题,带着问题看源码
待解答的问题
- 这段源码做了什么?
- 为什么这么做?
- 学到了哪些东西?
项目启动命令
使用远程debug的方式来启动,先将项目使用mvn package 命令打成jar包,然后cd到jar包所在目录,使用命令方式启动项目,我这里启动命令是:java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005 -Dlogging.level.root=info -jar spring-boot-learn-1.0-SNAPSHOT.jar --spring.profiles.active=profile --spring.main.lazy-initialization=false ,5005就是远程debug时的端口,然后通过idea来做远程debug,在启动过程一中有讲到远程debug的配置。
源码分析
4.5源码
这是Spring启动过程中最核心的代码,实例化bean、执行一些注册的后置处理器等都是在这个方法里实现的,所以单独一篇来看源码。
refreshContext(context);
private void refreshContext(ConfigurableApplicationContext context) {
// 刷想Spring上下文,整个Spring的核心逻辑
refresh(context);
//注册进程关闭的钩子,在这里会执行比如bean的destroy方法
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
}
catch (AccessControlException ex) {
// Not allowed in some environments.
}
}
}
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 源码4.5.1
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 源码4.5.2
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 源码4.5.3
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 源码4.5.4
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 源码4.5.5
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 遍历4.5.5里扫描到的BeanPostProcessor类,并调用getBean方法实例化后,加入BeanFactory容器的beanPostProcessors集合中,这里也会按照优先级来排序,实现了PriorityOrdered接口 > 实现了Ordered接口 > 其他
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 源码4.5.6
initMessageSource();
// Initialize event multicaster for this context.
// 向容器注册一个事件广播器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 实例化web容器,默认是tomcat
onRefresh();
// Check for listener beans and register them.
// 将扫描到的ApplicationListener注册到容器中
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 源码4.5.7
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// 源码4.5.8
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
下面一个一个看源码
4.5.1源码
记录开始日期,及一些配置的初始化,这个配置就是上一章讲到的Eviroment对象里的propertySources,这一个方法里没有什么重要的信息,直接跳过
prepareRefresh();
/**
* Prepare this context for refreshing, setting its startup date and
* active flag as well as performing any initialization of property sources.
*/
protected void prepareRefresh() {
// Switch to active.
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// Initialize any placeholder property sources in the context environment.
initPropertySources();
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
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<>();
}
4.5.2
通知子类去重新实例化一个beanFactory来替代当前上下文里的beanFactory,由于我们的context是AnnotationConfigServletWebServerApplicationContext,该类还是使用已经创建的beanFactory对象,所以这个方法没有做多余的操作,还是返回老的beanFactory的引用。
目前能想到需要刷新新的beanFactory的场景应该是支持实时装载新的bean时,比如从网络上加载xml文件并加载这个xml文件里的bean。AbstractRefreshableApplicationContext类已经提供了实例化新的beanFactory的实现,只要继承这个类就可以,下面截图里是这个类的子类:
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
/**
* Tell the subclass to refresh the internal bean factory.
* @return the fresh BeanFactory instance
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
/**
* Do nothing: We hold a single internal BeanFactory and rely on callers
* to register beans through our public methods (or the BeanFactory's).
* @see #registerBeanDefinition
*/
@Override
protected final void refreshBeanFactory() throws IllegalStateException {
if (!this.refreshed.compareAndSet(false, true)) {
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
this.beanFactory.setSerializationId(getId());
}
源码4.5.3
prepareBeanFactory(beanFactory);
/**
* Configure the factory's standard context characteristics,
* such as the context's ClassLoader and post-processors.
* @param beanFactory the BeanFactory to configure
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
// 设置Spring EL表达式的解析功能类
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
// 给GUI程序用的,此处可以忽略
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
// 注册后置处理器,这个类在下面看下源码
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 告知beanFactory忽略这些接口的方法上的依赖注入,因为这个方法上的注入由ApplicationContextAwareProcessor完成了
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 interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
// 添加ApplicationListener的后置处理器,比如一个ApplicationListener销毁前,将这个对象将ApplicationContext中删除,ApplicationListener实例化后,将这个监听器加到ApplicationContext中
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
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());
}
}
这里看下ApplicationContextAwareProcessor类的源码,这个类实现了BeanPostProcessor接口并实现了postProcessBeforeInitialization方法,这个方法就是在bean被实例化前会被容器调用,进而根据这些aware接口的相关set方法来将对应的对象注入进去,源码如下:
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
return bean;
}
AccessControlContext acc = null;
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
invokeAwareInterfaces(bean);
}
return bean;
}
// 根据bean的具体类型,调用相应的set方法,将对应的对象注入到bean里
private void invokeAwareInterfaces(Object bean) {
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);
}
}
这里我们经常用的有ApplicationContextAware接口,比如你的一个bean里需要用到Spring的applicationContext对象,那么可以定义一个自己的类并实现ApplicationContextAware接口,那么这个类就会自动将applicationContext对象注入到你的类里,通过这个对象可以访问这个上下文对象里的资源,如下:
public class MyApplicationContextAware implements ApplicationContextAware {
private ApplicationContextAware applicationContextAware;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContextAware = applicationContextAware;
}
}
这里可以看到ApplicationContextAwareProcessor已经负责了这些Aware类的资源注入逻辑,所以源码里才会将这些Aware类加入到ignore集合里
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
而这个ignore的意思并不是说实现了这些接口的类里的bean不再注入了,而是说在这些Aware接口的相应set方法上使用@Autowired注解会被忽视掉,比如这个@Autowired会被忽略:
public class MyApplicationContextAware implements ApplicationContextAware {
private ApplicationContextAware applicationContextAware;
@Override
@Autowired // 这个注解会被忽视
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContextAware = applicationContextAware;
}
}
源码4.5.4
postProcessBeanFactory(beanFactory);
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 调用父类的方法,详细看下面的代码2
super.postProcessBeanFactory(beanFactory);
// 当前项目里,这个if会直接跳过,这个scanner是扫描包路径下的所有类,把需要由Spring容器接管的类包装成BeanDefinition对象放到beanFactory里,后面会详细讲到,这里先跳过
if (this.basePackages != null && this.basePackages.length > 0) {
this.scanner.scan(this.basePackages);
}
// 当前项目里,这个if会被跳过,这个reader的作用就是解析所有beanDefinition里的注解,后面会详细讲到这里先跳过
if (!this.annotatedClasses.isEmpty()) {
this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
}
}
// 代码2
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 添加WebApplicationContextServletContextAwareProcessor后置处理器,该处理器作用是对于实现了ServletContextAware和ServletConfigAware接口的bean,会注入servletContext和servletConfig配置
beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));
// 由于实现ServletContextAware接口的setServletContext(ServletContext servletContext)已由上面那个后置处理器来完成了ServletContext对象的注入,所以这个接口上的Autowired注解会被忽视掉
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
registerWebApplicationScopes();
}
private void registerWebApplicationScopes() {
ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes(getBeanFactory());
WebApplicationContextUtils.registerWebApplicationScopes(getBeanFactory());
existingScopes.restore();
}
Scope就是告知Spring这个对象的生效范围,Spring容器默认是有两种Scope,singleton(单例)和prototype(多例),Spring默认是单例,但是可以通过@Scope(“prototype”)来对bean标注,告诉spring容器,这个bean每次都生成新的对象,registerWebApplicationScopes()方法是向beanFactory再注册request、session、application,,比如标注了@Scope(“request”),就是告诉Spring容器,当前这个对象在每个request请求过来时都生成一个新的对象,比如我们熟悉的HttpServletRequest对象,那session的意思就是每个链接生成一个。这个地方也是Spring容器的一个扩展点,可以定义自己的Scope,有兴趣的同学可以看这个博客
源码4.5.5
invokeBeanFactoryPostProcessors(beanFactory);
/**
* Instantiate and invoke all registered BeanFactoryPostProcessor beans,
* respecting explicit order if given.
* <p>Must be called before singleton instantiation.
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 执行所有的BeanFactory的后置处理器,具体看4.5.5.1解析
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
4.5.5.1解析
这个方法代码很长,主要作用就是执行已经注册的所有后置处理器,并且这些后置处理器按照固定顺序执行,先执行实现PriorityOrdered接口的,再执行实现Ordered接口的,最后执行剩余的后置处理器,主要步骤如下:
第一步:先执行方法中传入的beanFactoryPostProcessors集合的后置处理器逻辑(postProcessBeanDefinitionRegistry方法)
第二步:遍历容器中的BeanDefinitionRegistryPostProcessor类,执行实现了PriorityOrdered接口的后置处理器,包括重要的ConfigurationClassPostProcessor类(负责扫描包,加载所有的bean等重要逻辑)就是在这一步执行的
第三步:遍历容器中的BeanDefinitionRegistryPostProcessor类,执行实现了Ordered接口的后置处理器
第四步:遍历容器中的BeanDefinitionRegistryPostProcessor类,执行第二步和第三步剩下的后置处理器
第五步:BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor接口,所以第二、三、四里后置处理器也是BeanFactoryPostProcessor的实现类,这一步就是执行这些BeanFactoryPostProcessor的postProcessBeanFactory()方法
第六步:执行方法中传入的beanFactoryPostProcessors里的BeanFactoryPostProcessor的postProcessBeanFactory()方法
第七步:遍历出容器中注册的其他的BeanFactoryPostProcessor后置处理器,先执行实现PriorityOrdered接口的,再执行实现Ordered接口的,最后执行剩余的后置处理器
源码如下:
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
// 第一步
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 先获取后置处理器中的BeanDefinitionRegistryPostProcessors处理器来执行逻辑,这里的几个处理器对主流程作用不大,先跳过
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
// 执行后置处理逻辑
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 第二步
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// 这里是从beanFactory的beanDefinitionMap里获取BeanDefinitionRegistryPostProcessors里实现了PriorityOrdered接口的后置处理器来执行,这里有个非常重要的类ConfigurationClassPostProcessor在这里被执行,详细见后面的4.5.5.1.1解析
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);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 第三步
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
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();
}
// 第五步
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// 第六步
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// 第七步,遍历出实现了PriorityOrdered、Ordered接口的后置处理器,按顺序执行
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<>(orderedPostProcessorNames.size());
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<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
4.5.5.1.1解析
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);
}
}
// 排序,这个排序就是根据所实现的Ordered接口的getOrder()返回的值的大小来排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false)这个方法就是从beanFactory的beanDefinitionNames对象里根据类型获取对应的beanName,请看debug截图:
那这些类是何时被放到这个集合里的?在《启动过程五》里讲到了,有兴趣的可以去看下。这里有个非常重要的getBean(ppName, BeanDefinitionRegistryPostProcessor.class)方法,这里先看完主流程,这个方法在下一章节里单独讲。
这里有个非常重要的后置处理器ConfigurationClassPostProcessor.class,正是这个类开启了springboot从启动类Application.class开始牵出所有的bean的,我们要研究下这个代码。先看debug截图:
通过这个类的postProcessBeanDefinitionRegistry()方法,进入到核心的processConfigBeanDefinitions(BeanDefinitionRegistry registry)方法,代码如下:
/**
* Build and validate a configuration model based on the registry of
* {@link Configuration} classes.
*/
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
//详见下面的核心逻辑 第一步
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
//详见下面的核心逻辑 第二步
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// Return immediately if no @Configuration classes were found
if (configCandidates.isEmpty()) {
return;
}
// Sort by previously determined @Order value, if applicable
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
//详见下面的核心逻辑 第三步
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
//详见下面的核心逻辑 第四步
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.clear();
//详见下面的核心逻辑 第五步
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
上面的代码逻辑如下:
第一步、 先遍历所有的beanDefinitionNames,找到现有的beandefinition,debug截图如下:
那这里的这几个对象时什么时候插入到这个List beanDefinitionNames里的?在《启动过程六》里已经讲到。
第二步、 找出被@Configuration注解标注的类,这里就是我们的入口类,Application.class(该类被@SpringBootApplication标注,而@SpringBootApplication注解又被@SpringBootConfiguration标注,而@SpringBootConfiguration被@Configuration标注)debug图如下:
第三步、 通过ConfigurationClassParser来解析第二步中遍历出的类,主要是将被指定注解标注的类封装成ConfigurationClass放到parser对象的configurationClasses的Map里,供ConfigurationClassBeanDefinitionReader来做解析和加载,debug图如下:
public void parse(Set<BeanDefinitionHolder> configCandidates) {
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AnnotatedBeanDefinition) {
// parse方法里的逻辑看后面的解析,核心步骤3.1到3.8逻辑
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
// 核心步骤 3.9
this.deferredImportSelectorHandler.process();
}
parse方法会调到下面这个方法:
核心步骤如下:
- 3.1:如果该类被@Component标注(即使被@Component标注的注解标注也算,比如@Configuration注解被@Component标注了,如果该类被@Configuration标注,那么也就被@Component标注),那么先处理这个类里定义的一些内部类,对这些内部类递归调用processConfigurationClass(ConfigurationClass configClass)方法,先解析内部类,再解析外层类
- 3.2:判断是否有被@PropertySource标注,如果有这个注解,则将该注解的property配置文件里的key和value解析到Context的Environment对象里供后续使用
- 3.3:判断是否被@ComponentScans标注(这个注解就是告知Spring容器遍历那些包路径来加载bean),根据配置的包路径来扫描所有的类,对需要被Spring容器管理的类(被@Component注解的类)会递归调用下面这个方法,知道这类上的@ComponentScans注解里指定的包路径下的所有类都被扫描并解析到Spring容器里(这里如果没有配置包路径,默认为该类所在的包路径),这个扫描类的逻辑很多,后面单独拿出来解析源码,这里先看主流程,直接跳过。debug图如下:
- 3.4:当这个类没有被@ComponentScans标注后,开始解析@Import注解,这个注解的作用就是指定这个类需要由Spring容器管理
- 3.5:扫描这个类是否有被@ImportResource标注,如果有这个注解,则解析该注解,这个注解作用就是引进一xml配置,比如以前Spring项目里写了很多配置bean信息的xml文件,通过这个注解将这些bean配置文件加载进来,加载这些文件里的配置信息
- 3.6:解析类里被@Bean标注的方法
- 3.7:解析当前类的接口里的default方法,这里可以看出可以在接口的default方法上使用@Bean注解
- 3.8:查看该类是否有父类和父接口,如果有的话则递归调用processConfigurationClass()方法来解析
- 3.9:最后执行前几步中扫描出来的DeferredImportSelector类,比如我们自动加载的@EnableAutoConfiguration注解里@Import引入的用于加载自动组件的AutoConfigurationImportSelector类,这个接口类放在最后执行是因为这些自动加载的类很多都用到了@Conditional相关条件注解,比如@ConditionalOnMissingBean,所以需要等到其他bean已经扫描完后再执行这个类的逻辑
前八步的代码如下:
/**
* Apply processing and build a complete {@link ConfigurationClass} by reading the
* annotations, members and methods from the source class. This method can be called
* multiple times as relevant sources are discovered.
* @param configClass the configuration class being build
* @param sourceClass a source class
* @return the superclass, or {@code null} if none found or previously processed
*/
@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
// 3.1
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass);
}
// 3.2
// Process any @PropertySource annotations
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// 3.3
// Process any @ComponentScan annotations
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// 3.4
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), true);
// 3.5
// Process any @ImportResource annotations
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// 3.6
// Process individual @Bean methods
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// 3.7
// Process default methods on interfaces
processInterfaces(configClass, sourceClass);
// 3.8
// Process superclass, if any
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
// No superclass -> processing is complete
return null;
}
第四步、 通过ConfigurationClassBeanDefinitionReader来解析第三步中parser放到configurationClasses的Map里的ConfigurationClass,并解析成BeanDefinition注册到容器中,debug图如下:
/**
* Read a particular {@link ConfigurationClass}, registering bean definitions
* for the class itself and all of its {@link Bean} methods.
*/
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
// 先判断是否有@Conditional注解,有的话,校验条件是否满足,不满足条件,则从容器中删除
if (trackedConditionEvaluator.shouldSkip(configClass)) {
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
return;
}
// 将通过@Import注解引入的类封装成beanDefinition,注册到容器内
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
// 将通过@Bean标注的方法封装成BeanDefinition注册到容器内
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
// 加载@ImportResource指定的配置文件里的信息,加载配置文件里的beanDefinition
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
// 执行引入的ImportBeanDefinitionRegistrar类的registerBeanDefinitions方法,比如@EnableConfigurationProperties注解上的EnableConfigurationPropertiesRegistrar.class
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
这里的TrackedConditionEvaluator类就是解析@Conditional注解的,比如@ConditionalOnClass、@ConditionalOnBean等注解,原理就是这些注解上都会指定一个Condition接口的实现类,通过这个类的matches方法来判断是否符合条件,比如@ConditionalOnClass注解如下图:
而OnClassCondition类图如下:
而这里有个逻辑就是像@ConditionalOnBean这个注解的条件是必须已经加载了某个bean,在调用这个注解的matches方法时,需要等到所有的bean都扫描后,所以这里还有个阶段的概念,指定当前的matches方法是在哪个阶段做匹配,比如OnBeanCondition就指定只在注册阶段匹配:
而这个阶段的枚举有两个:
PARSE_CONFIGURATION:指的是在上面第三步里的parser的parse阶段,即:在扫描包路径并封装成ConfigurationClass阶段
REGISTER_BEAN:指的就是当前这一步的 reader的loadBeanDefinitionsForConfigurationClass阶段,即:将ConfigurationClass转成beanDefinition注册到容器阶段
第五步、 查看注册的所有的beanDefinition里是否有没有解析到的被@Configuration注解的类,因为被@Configuration注解的类会引入其他的bean,如果存在没有解析的类,则再循环走一遍整个逻辑,debug图如下:
4.5.6
作用就是配置国际化内容,比如需要根据当前的语言环境返回对应的字符,可以看这个博客
initMessageSource();InstantiationAwareBeanPostProcessor
4.5.7
作用就是讲4.5.5里注册到容器内的BeanDefinition进行实例化,这个getBean()实例化bean的过程会单独拿一节讲解,这里先看下debug图:
finishBeanFactoryInitialization(beanFactory);
/**
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
代码4.5.7
主要逻辑:
1、清除缓存
2、执行容器内的实现了LifecycleProcessor接口的bean的onRefresh方法,如果没有LifecycleProcessor类,则添加默认的DefaultLifecycleProcessor,这个类的onRefresh方法就是找到beanFactory内的实现了Lifecycle接口的bean,执行这些bean的start方法,源码debug图如下:
3、发布onRefresh事件,在启动过程三中发布过starting事件,在那个源码分析中,讲了怎么通过事件类型来匹配Listener,这里就不重复了,有兴趣的到《启动过程三》看下
4、启动web容器,比如tomcat或者undertow等容器,这个启动过程会在后面单独一节讲到
@Override
protected void finishRefresh() {
super.finishRefresh();
// 启动web容器
WebServer webServer = startWebServer();
if (webServer != null) {
publishEvent(new ServletWebServerInitializedEvent(webServer, this));
}
}
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
clearResourceCaches();
// Initialize lifecycle processor for this context.
// 如果beanFactory里没有注册LifecycleProcessor,则添加默认的DefaultLifecycleProcessor
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
// 执行所有LifecycleProcessor的onRefresh方法
getLifecycleProcessor().onRefresh();
// Publish the final event.
// 发布refresh事件,由容器中监听该事件的Listener执行相应逻辑
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
4.6源码
将启动命令里的命令行参数传给容器内的ApplicationRunner和CommandLineRunner接口的实现类,执行他们的run方法,比如我们的启动命令是java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005 -Dlogging.level.root=info -jar spring-boot-learn-1.0-SNAPSHOT.jar --spring.profiles.active=profile --spring.main.lazy-initialization=false,这个命令行参数就是jar包名字后面的–spring.profiles.active=profile --spring.main.lazy-initialization=false,Spring默认是没有配置,这里可以自定义做扩展,debug图如下:
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList<>();
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
AnnotationAwareOrderComparator.sort(runners);
for (Object runner : new LinkedHashSet<>(runners)) {
if (runner instanceof ApplicationRunner) {
callRunner((ApplicationRunner) runner, args);
}
if (runner instanceof CommandLineRunner) {
callRunner((CommandLineRunner) runner, args);
}
}
}
private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
try {
(runner).run(args);
}
catch (Exception ex) {
throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
}
}
private void callRunner(CommandLineRunner runner, ApplicationArguments args) {
try {
(runner).run(args.getSourceArgs());
}
catch (Exception ex) {
throw new IllegalStateException("Failed to execute CommandLineRunner", ex);
}
}
总结及思考
这段源码做了什么?
这个refresh(context)是springboot最核心的启动逻辑,而这个核心方法的核心逻辑又是通过各种后置处理器来完成的,包括spring的ConfigurationClassPostProcessor.class后置处理器来实现扫描包路径,将需要管理的类分装成beanDefinition注册到beanFactory容器里,最后实例化bean及属性注入。refresh()方法的核心步骤如下:
1、prepareRefresh() 为contex的refresh初始化property sources(环境变量、命令行参数、springboot的配置文件等),一些初始化的参数
2、prepareBeanFactory(beanFactory) 为beanFactory设置基础功能类(比如:ApplicationContextAwareProcessor类负责各种Aware类的注入),包括一些后置处理器、设置类加载器等
3、postProcessBeanFactory(beanFactory); 如4.5.4讲解的,主要是注册WebApplicationContextServletContextAwareProcessor(负责实现ServletContextAware和ServletConfigAware接口的bean里的属性注入)、注册web中的三种scope
4、** invokeBeanFactoryPostProcessors(beanFactory);** 按照一定的排序来执行beanFactory里现有的后置处理器的后置逻辑,这里就包括最重要的ConfigurationClassPostProcessor.class后置处理器的逻辑,也是在这一步里扫表包路径,加载beanDefinition,详细见4.5.5源码分析 5、registerBeanPostProcessors(beanFactory); 在第4步骤会扫描出很多新的后置处理器,这一步就是将扫描到新的后置处理器实例化,并注册到beanFactory里
6、onRefresh(); 实例化web容器,当期那2.x版本里默认的是tomcat
7、finishBeanFactoryInitialization(beanFactory); 实例化所有注册到beanFactory里的beanDefinition,这里就是调用beanFactory的getBean方法来实现实例化
8、finishRefresh(); 执行LifecycleProcessor的处理逻辑、发布ContextRefreshedEvent事件、启动web容器等扫尾工作
学到了哪些东西?
这里可以看到我们在开发过程中可以扩展自己的后置处理器,而比如redis、mybatis的各种注解能起作用,都是因为他们扩展了后置处理器,在后置处理器里加上了自己的解析逻辑 生成对应的代理来实现的,这里画了一个context生命周期期间,各种后置处理器生效的时间点的图,我们可以根据场景需要进行扩展: