文章图片
首先启动项目,跟踪方法调用栈:
文章图片
1,触发时刻:
首先知道当spring容器启动时会执行 refresh()
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {prepareRefresh();
// 用于获得一个新的 BeanFactory。该方法会解析所有 Spring 配置文件ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 准备bean工厂
prepareBeanFactory(beanFactory);
try {// spring的预留接口
postProcessBeanFactory(beanFactory);
// spring核心方法,实例化和调用所有 BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// 注册所有的bean 注册所有的到 beanPostProcessors的List中
registerBeanPostProcessors(beanFactory);
// 初始化国际化信息
initMessageSource();
// 初始化单例的广播器,之后注册监听器、发布事件都基于该广播器执行
initApplicationEventMulticaster();
// 属于spring的预留接口,在后面的版本中扩展
onRefresh();
// 注册监听器到广播器中
registerListeners();
// spring核心 实例化bean,bean的整个生命周期也从这里开始
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
} catch (BeansException ex) {destroyBeans();
cancelRefresh(ex);
throw ex;
} finally {
resetCommonCaches();
}
}
这里主要看:
// 初始化单例的广播器,之后注册监听器、发布事件都基于该广播器执行
initApplicationEventMulticaster();
org.springframework.context.support.AbstractApplicationContext#initApplicationEventMulticaster
protected void initApplicationEventMulticaster() {
// 获取bean工厂
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 是否有 applicationEventMulticaster这个beanName
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
// 存在则实例化这个bean
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
}
else {
// 否则new 一个SimpleApplicationEventMulticaster 并注册单例到bean工厂
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
}
}
// 注册监听器到广播器中
registerListeners();
org.springframework.context.support.AbstractApplicationContext#registerListeners
// 注册到广播器
// Add beans that implement ApplicationListener as listeners. Doesn't affect other listeners, which can be added without being beans
// 添加将ApplicationListener实现为侦听器的bean。不影响其他监听器,可以添加而不是bean
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!
// 获取所的 监听器 添加到广播器的BeanName
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...
// 在prepareRefresh()之后 ,registerListeners()之前、的都会缓存在这里进行统一发布
// multicastEvent方法具体实现放在发布过程详解
Set earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
@Override
public void addApplicationListener(ApplicationListener> listener) {
synchronized (this.retrievalMutex) {
// Explicitly remove target for a proxy, if registered already,
// in order to avoid double invocations of the same listener.
Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
if (singletonTarget instanceof ApplicationListener) {
this.defaultRetriever.applicationListeners.remove(singletonTarget);
}
this.defaultRetriever.applicationListeners.add(listener);
this.retrieverCache.clear();
}
} @Override
public void addApplicationListenerBean(String listenerBeanName) {
synchronized (this.retrievalMutex) {
this.defaultRetriever.applicationListenerBeans.add(listenerBeanName);
this.retrieverCache.clear();
}
}
就是放到这个对象里了
文章图片
文章图片
上述就是容器自己启动时发布的事件:
在上下中还有个发布的事件的地方:
@RunWith(value = https://www.it610.com/article/SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
public class ListenerTest implements ApplicationContextAware {
private static Logger logger = LoggerFactory.getLogger(ListenerTest.class);
private ApplicationContext context = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
@Test
public void listener() {
context.publishEvent(new MyEvent(this,"事件测试"));
}
}
@Override
public void publishEvent(ApplicationEvent event) {
publishEvent(event, null);
}protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
// 判断事件源是否实现了ApplicationEvent接口并进行转化
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
// 如果没有也要封装成ApplicationEvent事件
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent>) applicationEvent).getResolvableType();
}
} // 在初始化应用上下文预处理方法(prepareRefresh)之后,注册监听器方法(registerListeners)之前,这期间的发布全部进行延迟发布,交由registerListeners方法统一发布
// 此时earlyApplicationEvents为null
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
// 获取广播器并发布事件
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
} // 通过父上下文发布事件
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
我们发现调用的都是这个multicastEvent()
我们看下是怎么发布事件的:
org.springframework.context.event.SimpleApplicationEventMulticaster#multicastEvent(org.springframework.context.ApplicationEvent)
@Override
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, resolveDefaultEventType(event));
}@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
// 包装事件源,可以方便解析事件源的泛型
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
// 获取任务执行(默认为空)
Executor executor = getTaskExecutor();
// 通过事件源和事件类型获取感知的监听器后遍历发布
for (ApplicationListener> listener : getApplicationListeners(event, type)) {
// 如果有设置任务执行则使用任务执行发布
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
// 如果没有设置任务执行则直接发布
invokeListener(listener, event);
}
}
}
看到这大概就懂了 ,getApplicationListeners()获取对应事件的监听器 ,再循环监听器,执行这个事件。
org.springframework.context.event.AbstractApplicationEventMulticaster#getApplicationListeners(org.springframework.context.ApplicationEvent, org.springframework.core.ResolvableType)
protected Collection> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {
// 获取事件的源
Object source = event.getSource();
// 事件源的类型
Class> sourceType = (source != null ? source.getClass() : null);
// 一个简单类,当做map的key使用,用以区分不同的事件类型并设置缓存
ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
// 尝试从缓存获取
ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
// 如果缓存不为空则返回监听器列表
if (retriever != null) {
return retriever.getApplicationListeners();
} // 判断类是否可以缓存的
if (this.beanClassLoader == null
|| (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
// Fully synchronized building and caching of a ListenerRetriever
synchronized (this.retrievalMutex) {
// 典型的单例,再次尝试获取缓存
retriever = this.retrieverCache.get(cacheKey);
if (retriever != null) {
return retriever.getApplicationListeners();
}
// 创建缓存的数据
retriever = new ListenerRetriever(true);
// 通过事件源查找符合的监听器
Collection> listeners = retrieveApplicationListeners(eventType, sourceType, retriever);
// 设置缓存
this.retrieverCache.put(cacheKey, retriever);
return listeners;
}
}
else {
// 通过事件源查找符合的监听器
return retrieveApplicationListeners(eventType, sourceType, null);
}
}
private Collection> retrieveApplicationListeners(
ResolvableType eventType, @Nullable Class> sourceType, @Nullable ListenerRetriever retriever) { // 查找的监听器集合
List> allListeners = new ArrayList<>();
Set> listeners;
Set listenerBeans;
synchronized (this.retrievalMutex) {
// 获取前面注册监听器方法(registerListeners)注册的监听器
listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
} // 遍历硬编码注册的监听器
for (ApplicationListener> listener : listeners) {
// 判断是否符合监听器
if (supportsEvent(listener, eventType, sourceType)) {
if (retriever != null) {
// 为缓存添加的
retriever.applicationListeners.add(listener);
}
// 添加到查找到的监听器中
allListeners.add(listener);
}
} // 解析通过实现ApplicationListener接口的监听器
if (!listenerBeans.isEmpty()) {
// 获取bean工厂
ConfigurableBeanFactory beanFactory = getBeanFactory();
for (String listenerBeanName : listenerBeans) {
try {
// 判断是否符合监听器
if (supportsEvent(beanFactory, listenerBeanName, eventType)) {
// 通过bean工厂获取监听器
ApplicationListener> listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class);
// 如果不存在结果集中并且符合需要感知的监听器
if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
// 如果需要缓存
if (retriever != null) {
// 如果是单例,则添加监听器到缓存,否则添加beanName缓存
if (beanFactory.isSingleton(listenerBeanName)) {
retriever.applicationListeners.add(listener);
}
else {
retriever.applicationListenerBeans.add(listenerBeanName);
}
}
// 添加到查找到的监听器中
allListeners.add(listener);
}
}
else {
// 删除不符合感知的监听器需要移除对应的缓存和监听器结果
Object listener = beanFactory.getSingleton(listenerBeanName);
if (retriever != null) {
retriever.applicationListeners.remove(listener);
}
allListeners.remove(listener);
}
}
catch (NoSuchBeanDefinitionException ex) {
// Singleton listener instance (without backing bean definition) disappeared -
// probably in the middle of the destruction phase
}
}
} // 对监听器排序,如果存在@Order注解
AnnotationAwareOrderComparator.sort(allListeners);
// 如果applicationListenerBeans为空说明监听器全部在allListeners里,则清空applicationListeners重新添加即可
// applicationListenerBeans为空说明没有非单例bean
if (retriever != null && retriever.applicationListenerBeans.isEmpty()) {
retriever.applicationListeners.clear();
retriever.applicationListeners.addAll(allListeners);
}
// 反正最终查找到的监听器
return allListeners;
}
org.springframework.context.event.SimpleApplicationEventMulticaster#invokeListener
事件执行:
protected void invokeListener(ApplicationListener> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event);
}
}
【springboot|Springboot 启动流程源码解析(广播器,以及内嵌tomcat启动)】2,MVC容器初始化
我们在创建springMvc项目时会再启动的配置中配置一个ContextLoaderListener
比如传统的XML:
contextConfigLocationclasspath*:applictionContext.xml
org.springframework.web.context.ContextLoaderListener
dispatcher-servlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocationclasspath*:springMVC-conf.xml
dispatcher-servlet
/*
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
public ContextLoaderListener() {
} public ContextLoaderListener(WebApplicationContext context) {
super(context);
} @Override
public void contextInitialized(ServletContextEvent event) {
initWebApplicationContext(event.getServletContext());
} @Override
public void contextDestroyed(ServletContextEvent event) {
closeWebApplicationContext(event.getServletContext());
ContextCleanupListener.cleanupAttributes(event.getServletContext());
}
}
触发上下文: WebApplicationContext实例
//ContextLoader.java
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
//初始化Spring容器时如果发现servlet 容器中已存在根Spring容根器则抛出异常,证明rootWebApplicationContext只能有一个。
if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
throw new IllegalStateException(
"Cannot initialize context because there is already a root application context present - " +
"check whether you have multiple ContextLoader* definitions in your web.xml!");
} try {
//创建webApplicationContext实例
if (this.context == null) {
this.context = createWebApplicationContext(servletContext);
}
if (this.context instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
if (!cwac.isActive()) {
if (cwac.getParent() == null) {
ApplicationContext parent = loadParentContext(servletContext);
cwac.setParent(parent);
}
//配置WebApplicationContext
configureAndRefreshWebApplicationContext(cwac, servletContext);
}
}/**
把生成的webApplicationContext设置成root WebApplicationContext。保存在ServletContext上下文中。
下一步初始化MVC ApplicationContext时需要从ServletContext取出根上下文作为其父上下文。
**/
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
if (ccl == ContextLoader.class.getClassLoader()) {
currentContext = this.context;
}
else if (ccl != null) {
currentContextPerThread.put(ccl, this.context);
}return this.context;
}
catch (RuntimeException | Error ex) {
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
throw ex;
}
}
Springboot内嵌tomcat后 是如何启动的呢?
既然我们想知道tomcat在SpringBoot中是怎么启动的,那么run方法中,重点关注创建应用上下文(createApplicationContext)和刷新上下文(refreshContext)。
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection exceptionReporters = new ArrayList();
this.configureHeadlessProperty();
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting();
Collection exceptionReporters;
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
this.configureIgnoreBeanInfo(environment);
Banner printedBanner = this.printBanner(environment);
// 创建上下文
context = this.createApplicationContext();
exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 刷新上下文 就是上文代码中的 refresh() 那。。。
this.refreshContext(context);
this.afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}listeners.started(context);
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
}try {
listeners.running(context);
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}
1设置系统属性『java.awt.headless』,为true则启用headless模式支持;
2,通过 SpringFactoriesLoader 检索 META-INF/spring.factories ,找到声明的所有SpringApplicationRunListener的实现类并将其实例化,之后逐个调用其started()方法,广播SpringBoot要开始执行了;
3 发布应用开始启动事件;
4 初始化参数
5 创建并配置当前SpringBoot应用将要使用的Environment(包括配置要使用的PropertySource以及Profile),并遍历调用所有的SpringApplicationRunListener的environmentPrepared()方法,广播Environment准备完毕。
6 打印banner;
7 创建应用上下文;
8 通过SpringFactoriesLoader检索META-INF/spring.factories,获取并实例化异常分析器;
9 为ApplicationContext加载environment,之后逐个执行ApplicationContextInitializer的initialize()方法来进一步封装ApplicationContext,并调用所有的SpringApplicationRunListener的contextPrepared()方法,【EventPublishingRunListener只提供了一个空的contextPrepared()方法】,之后初始化IoC容器,并调用SpringApplicationRunListener的contextLoaded()方法,广播ApplicationContext的IoC加载完成,这里就包括通过@EnableAutoConfiguration导入的各种自动配置类;
10 刷新上下文;
11 再一次刷新上下文,实现类扩展;
12发布应用已经启动的事件;
13遍历所有注册的ApplicationRunner和CommandLineRunner,并执行其run()方法(可以实现自己的ApplicationRunner或者CommandLineRunner,来对SpringBoot的启动过程进行扩展);
14 应用已经启动完成的监听事件。
也就是:
1. 配置属性 > 2. 获取监听器,发布应用开始启动事件 > 3. 初始化输入参数 > 4. 配置环境,输出 banner > 5. 创建上下文 > 6. 预处理上下文 > 7. 刷新上下文 > 8. 再刷新上下文 > 9. 发布应用已经启动事件 > 10. 发布应用启动完成事件。
创建上下文:
//创建上下文
protected ConfigurableApplicationContext createApplicationContext() {
Class> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch(this.webApplicationType) {
case SERVLET:
//创建AnnotationConfigServletWebServerApplicationContext
contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");
break;
case REACTIVE:
contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");
break;
default:
contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");
}
} catch (ClassNotFoundException var3) {
throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);
}
} return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
}
文章图片
创建AnnotationConfigServletWebServerApplicationContext类。
而AnnotationConfigServletWebServerApplicationContext类继承了ServletWebServerApplicationContext,而这个类是最终集成了AbstractApplicationContext
刷新上下文:
run() -> this.refreshContext(context) ->refresh() .. -> onRefresh();
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#onRefresh
protected void onRefresh() {
super.onRefresh();
try {
this.createWebServer();
} catch (Throwable var2) {
throw new ApplicationContextException("Unable to start web server", var2);
}
}
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = this.getServletContext();
if (webServer == null && servletContext == null) {ServletWebServerFactory factory = this.getWebServerFactory();
// 创建一个WebServer
this.webServer = factory.getWebServer(new ServletContextInitializer[]{this.getSelfInitializer()});
} else if (servletContext != null) {
try {
this.getSelfInitializer().onStartup(servletContext);
} catch (ServletException var4) {
throw new ApplicationContextException("Cannot initialize servlet context", var4);
}
}this.initPropertySources();
}
文章图片
public WebServer getWebServer(ServletContextInitializer... initializers) {
Tomcat tomcat = new Tomcat();
File baseDir = this.baseDirectory != null ? this.baseDirectory : this.createTempDir("tomcat");
tomcat.setBaseDir(baseDir.getAbsolutePath());
Connector connector = new Connector(this.protocol);
tomcat.getService().addConnector(connector);
this.customizeConnector(connector);
tomcat.setConnector(connector);
tomcat.getHost().setAutoDeploy(false);
this.configureEngine(tomcat.getEngine());
Iterator var5 = this.additionalTomcatConnectors.iterator();
while(var5.hasNext()) {
Connector additionalConnector = (Connector)var5.next();
tomcat.getService().addConnector(additionalConnector);
}this.prepareContext(tomcat.getHost(), initializers);
return this.getTomcatWebServer(tomcat);
}
那么他的那些:
DispatcherServlet ..需要的Bean在哪里配置了呢 看下图
在 org.springframework.boot.autoconfigure 中有如下配置。
文章图片
@Configuration
@Conditional({DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition.class})
@ConditionalOnClass({ServletRegistration.class})
@EnableConfigurationProperties({HttpProperties.class, WebMvcProperties.class})
protected static class DispatcherServletConfiguration {
private final HttpProperties httpProperties;
private final WebMvcProperties webMvcProperties;
public DispatcherServletConfiguration(HttpProperties httpProperties, WebMvcProperties webMvcProperties) {
this.httpProperties = httpProperties;
this.webMvcProperties = webMvcProperties;
}@Bean(
name = {"dispatcherServlet"}
)
public DispatcherServlet dispatcherServlet() {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
dispatcherServlet.setDispatchOptionsRequest(this.webMvcProperties.isDispatchOptionsRequest());
dispatcherServlet.setDispatchTraceRequest(this.webMvcProperties.isDispatchTraceRequest());
dispatcherServlet.setThrowExceptionIfNoHandlerFound(this.webMvcProperties.isThrowExceptionIfNoHandlerFound());
dispatcherServlet.setEnableLoggingRequestDetails(this.httpProperties.isLogRequestDetails());
return dispatcherServlet;
}@Bean
@ConditionalOnBean({MultipartResolver.class})
@ConditionalOnMissingBean(
name = {"multipartResolver"}
)
public MultipartResolver multipartResolver(MultipartResolver resolver) {
return resolver;
}
}
因为spring的自动装配已经加载好了他:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
Target(ElementType.TYPE)
Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
Class>[] exclude() default {};
/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
String[] excludeName() default {};
其中引入了@Import(AutoConfigurationImportSelector.class) 他是真正实现自动装配的关键类。
文章图片
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//1.是否开启自动配置,默认开启
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
//2.从META-INF/spring-autoconfigure-metadata.properties文件中载入属性配置(有一些有默认值),获取注解信息
AutoConfigurationMetadata autoConfigurationMetadata = https://www.it610.com/article/AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
//3.获取所有的配置列表
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
public static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader) {
return loadMetadata(classLoader, "META-INF/spring-autoconfigure-metadata.properties");
}
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
List configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
configurations = this.removeDuplicates(configurations);
Set exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = this.filter(configurations, autoConfigurationMetadata);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
}
}
protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}
上述代码说明加载了两文件中的:
META-INF/spring.factories和META-INF/spring-autoconfigure-metadata.properties 的文件的class的路径:
文章图片
package org.springframework.context.annotation;
import org.springframework.core.type.AnnotationMetadata;
/**
* Interface to be implemented by types that determine which @{@link Configuration}
* class(es) should be imported based on a given selection criteria, usually one or more
* annotation attributes.
*
* An {@link ImportSelector} may implement any of the following
* {@link org.springframework.beans.factory.Aware Aware} interfaces, and their respective
* methods will be called prior to {@link #selectImports}:
*
* - {@link org.springframework.context.EnvironmentAware EnvironmentAware}
* - {@link org.springframework.beans.factory.BeanFactoryAware BeanFactoryAware}
* - {@link org.springframework.beans.factory.BeanClassLoaderAware BeanClassLoaderAware}
* - {@link org.springframework.context.ResourceLoaderAware ResourceLoaderAware}
*
*
* ImportSelectors are usually processed in the same way as regular {@code @Import}
* annotations, however, it is also possible to defer selection of imports until all
* {@code @Configuration} classes have been processed (see {@link DeferredImportSelector}
* for details).
*
* @author Chris Beams
* @since 3.1
* @see DeferredImportSelector
* @see Import
* @see ImportBeanDefinitionRegistrar
* @see Configuration
*/
public interface ImportSelector {
/**
* Select and return the names of which class(es) should be imported based on
* the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
*/
String[] selectImports(AnnotationMetadata importingClassMetadata);
什么时候调用的这个方法?
如果该接口的实现类同时实现
EnvironmentAware
, BeanFactoryAware
,BeanClassLoaderAware
或者ResourceLoaderAware
,那么在调用其selectImports方法之前先调用上述接口中对应的方法,如果需要在所有的@Configuration
处理完在导入时可以实现DeferredImportSelector(延迟导入)接口。ConfigurationClassPostProcessor
org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanFactory
->newConfigurationClassParser()
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
// 解析各种注解用的
@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass);
}// 解析 @PropertySource 注解
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");
}
}// 解析 @ComponentScan
Set 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 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());
}
}
}
}// 解析 @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), true);
// 解析 @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);
}
}// 解析 @Bean 方法
Set beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}// Process default methods on interfaces
processInterfaces(configClass, sourceClass);
// 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;
}
看这块就是读取所有的impor注解的地方:
processImports(configClass, sourceClass, getImports(sourceClass), true);
这里会把上边的所有的导入的class。
那么这个方法是在什么时候执行的?
就是在上边 refresh()方法中的
invokeBeanFactoryPostProcessors(): 实例化和调用所有 BeanFactoryPostProcessor
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
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()));
}
}
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
private static void invokeBeanFactoryPostProcessors(
Collection extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
}
postProcessBeanFactory 作用:在应用程序上下文的标准初始化之后修改其内部bean工厂。所有bean定义都将被加载,但是还没有bean被实例化,这允许覆盖或添加属性。
end。
推荐阅读
- 编程|手写Spring核心原理MVC实现
- Spring|《SpringBoot启动流程六》(源码分析SpringBoot如何内嵌并启动Tomcat服务器的())
- 详细讲解Spring中的@Bean注解
- ★推荐一款适用于SpringBoot项目的轻量级HTTP客户端框架
- #yyds干货盘点# Spring Boot的前世今生以及它和Spring Cloud的关系详解。
- 老王读Spring IoC-3Spring bean 的创建过程
- Springboot docker jenkins 自动化部署并上传镜像
- SpringBoot加email服务,你说有没有搞头()
- springboot