共计 24372 个字符,预计需要花费 61 分钟才能阅读完成。
springboot 系列之启动流程
Springboot 简介
springboot 封装了 Spring 组件,基于约定优于配置。晋升了开发效率,本文次要解说 springboot 框架的启动过程。
启动流程剖析
1、首先,咱们看一下启动类 SpringApplication, 它是位于 org.springframework.boot 包上面的。我的项目启动类源码
@SpringBootApplication | |
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args); | |
} | |
} |
这里用到了 SpringBootApplication 注解,而后在 main 办法中启动 boot 利用。
2、咱们接下来看看 SpringBootApplication 注解的源码
@Target(ElementType.TYPE) | |
@Retention(RetentionPolicy.RUNTIME) | |
@Documented | |
@Inherited | |
@SpringBootConfiguration | |
@EnableAutoConfiguration | |
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), | |
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) | |
public @interface SpringBootApplication { | |
/** | |
* Exclude specific auto-configuration classes such that they will never be applied. | |
* @return the classes to exclude | |
*/ | |
@AliasFor(annotation = EnableAutoConfiguration.class) | |
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 | |
*/ | |
@AliasFor(annotation = EnableAutoConfiguration.class) | |
String[] excludeName() default {}; | |
/** | |
* Base packages to scan for annotated components. Use {@link #scanBasePackageClasses} | |
* for a type-safe alternative to String-based package names. | |
* @return base packages to scan | |
* @since 1.3.0 | |
*/ | |
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages") | |
String[] scanBasePackages() default {}; | |
/** | |
* Type-safe alternative to {@link #scanBasePackages} for specifying the packages to | |
* scan for annotated components. The package of each class specified will be scanned. | |
* <p> | |
* Consider creating a special no-op marker class or interface in each package that | |
* serves no purpose other than being referenced by this attribute. | |
* @return base packages to scan | |
* @since 1.3.0 | |
*/ | |
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses") | |
Class<?>[] scanBasePackageClasses() default {};} |
它是位于 org.springframework.boot.autoconfigure 包上面的。咱们能够看到它依赖了几个重要的注解 SpringBootConfiguration、EnableAutoConfiguration、ComponentScan 这三个注解。其中 EnableAutoConfiguration 就是 springboot 主动配置用到的类,在接下来咱们将会重点介绍。
3、咱们在看 SpringApplication 运行的 run 办法
/** | |
* Static helper that can be used to run a {@link SpringApplication} from the | |
* specified sources using default settings and user supplied arguments. | |
* @param primarySources the primary sources to load | |
* @param args the application arguments (usually passed from a Java main method) | |
* @return the running {@link ApplicationContext} | |
*/ | |
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {return new SpringApplication(primarySources).run(args); | |
} |
首先,创立 SpringApplication 利用对象,而后调用 run 办法传入启动参数
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { | |
this.resourceLoader = resourceLoader; | |
Assert.notNull(primarySources, "PrimarySources must not be null"); | |
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); | |
this.webApplicationType = WebApplicationType.deduceFromClasspath(); | |
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); | |
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); | |
this.mainApplicationClass = deduceMainApplicationClass();} |
this.webApplicationType = WebApplicationType.deduceFromClasspath(); | |
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); | |
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); | |
this.mainApplicationClass = deduceMainApplicationClass(); |
这是创建对象的办法,先校验启动类,而后调用 deduceFromClasspath 办法推断一个利用类型(是否是 web 我的项目)初始化工厂类,设置 Spring 监听器(观察者模式)。
4、创立好对象后,咱们接着看 run 办法
/** | |
* Run the Spring application, creating and refreshing a new | |
* {@link ApplicationContext}. | |
* @param args the application arguments (usually passed from a Java main method) | |
* @return a running {@link ApplicationContext} | |
*/ | |
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); | |
// 配置疏忽的 bean 信息 | |
configureIgnoreBeanInfo(environment); | |
// 打印 boot 启动 logo | |
Banner printedBanner = printBanner(environment); | |
// 创立上线文(容器)context = createApplicationContext(); | |
// 获取异样汇合 | |
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, | |
new Class[] { ConfigurableApplicationContext.class}, context); | |
// 筹备上下文 | |
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); | |
} | |
catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, listeners); | |
throw new IllegalStateException(ex); | |
} | |
try {listeners.running(context); | |
} | |
catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, null); | |
throw new IllegalStateException(ex); | |
} | |
return context; | |
} |
咱们只看几个重要的办法,首先看 createApplicationContext() 创立上下文(容器)办法
/** | |
* Strategy method used to create the {@link ApplicationContext}. By default this | |
* method will respect any explicitly set application context or application context | |
* class before falling back to a suitable default. | |
* @return the application context (not yet refreshed) | |
* @see #setApplicationContextClass(Class) | |
*/ | |
protected ConfigurableApplicationContext createApplicationContext() { | |
// 获取启动类 | |
Class<?> contextClass = this.applicationContextClass; | |
// 推断上下文类型,默认 web 类型,if (contextClass == null) { | |
try {switch (this.webApplicationType) { | |
case SERVLET: | |
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS); | |
break; | |
//flux 类型上下文 | |
case REACTIVE: | |
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS); | |
break; | |
default: | |
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS); | |
} | |
} | |
catch (ClassNotFoundException ex) { | |
throw new IllegalStateException( | |
"Unable create a default ApplicationContext," + "please specify an ApplicationContextClass", | |
ex); | |
} | |
} | |
// 实例化上下文,容器 | |
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass); | |
} |
咱们在看,prepareContext(context, environment, listeners, applicationArguments, printedBanner); 筹备上下文办法
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, | |
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { | |
// 设置上下文环境 | |
context.setEnvironment(environment); | |
// 解决利用上下文 | |
postProcessApplicationContext(context); | |
// 利用初始化类 | |
applyInitializers(context); | |
// 监听器筹备上下文 | |
listeners.contextPrepared(context); | |
if (this.logStartupInfo) {logStartupInfo(context.getParent() == null); | |
logStartupProfileInfo(context); | |
} | |
// Add boot specific singleton beans | |
// 创立 bean 工厂 | |
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); | |
// 注册利用参数 bean | |
beanFactory.registerSingleton("springApplicationArguments", applicationArguments); | |
if (printedBanner != null) {beanFactory.registerSingleton("springBootBanner", printedBanner); | |
} | |
if (beanFactory instanceof DefaultListableBeanFactory) {((DefaultListableBeanFactory) beanFactory) | |
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); | |
} | |
// Load the sources | |
Set<Object> sources = getAllSources(); | |
Assert.notEmpty(sources, "Sources must not be empty"); | |
load(context, sources.toArray(new Object[0])); | |
listeners.contextLoaded(context); | |
} |
在看、重要的 refreshContext(context); 刷新上下文办法重点
private void refreshContext(ConfigurableApplicationContext context) {refresh(context); | |
if (this.registerShutdownHook) { | |
try {context.registerShutdownHook(); | |
} | |
catch (AccessControlException ex) {// Not allowed in some environments.} | |
} | |
} |
点进去 refresh(context); 办法进入
/** | |
* Refresh the underlying {@link ApplicationContext}. | |
* @param applicationContext the application context to refresh | |
*/ | |
protected void refresh(ApplicationContext applicationContext) {Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext); | |
((AbstractApplicationContext) applicationContext).refresh();} |
类型转换为 AbstractApplicationContext,持续看 refresh 办法
@Override | |
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) { | |
// 筹备刷新 | |
prepareRefresh(); | |
// 刷新子类工厂 | |
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); | |
// 筹备 beanFactory | |
prepareBeanFactory(beanFactory); | |
try { | |
// 解决 bean 工厂 | |
postProcessBeanFactory(beanFactory); | |
// 调用 bean 共产处理器重点 | |
invokeBeanFactoryPostProcessors(beanFactory); | |
// 注册 bean 工厂处理器 | |
registerBeanPostProcessors(beanFactory); | |
// 初始化音讯类 | |
initMessageSource(); | |
// 初始化利用事件播送 | |
initApplicationEventMulticaster(); | |
// 正在刷新的 | |
onRefresh(); | |
// 公布事件监听器 | |
registerListeners(); | |
// 实现 bean 工厂注册 | |
finishBeanFactoryInitialization(beanFactory); | |
// 实现事件刷新 | |
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();} | |
} | |
} |
咱们在看 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() { | |
// 启动利用开关 | |
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()); | |
} | |
} | |
// 初始化属性类 | |
initPropertySources(); | |
// 校验属性 | |
// 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<>();} |
在看 prepareBeanFactory 筹备配置工厂办法
/** | |
* 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) { | |
// 设置类加载器 | |
beanFactory.setBeanClassLoader(getClassLoader()); | |
// 设置 bean 表达式解决 | |
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); | |
// 设置属性编辑器注册 | |
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); | |
// 配置 bean 处理器,后置解决 | |
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 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); | |
// 增加事件监听处理器 | |
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)) {// 注册环境 bean 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()); | |
} | |
} |
在看 postProcessBeanFactory(beanFactory); 解决工厂类(子类)
在 ServletWebServerApplicationContext 类中实现了这个办法 | |
@Override | |
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this)); | |
beanFactory.ignoreDependencyInterface(ServletContextAware.class); | |
registerWebApplicationScopes();} |
在看 invokeBeanFactoryPostProcessors(beanFactory); 调用 bean 工厂处理器办法
/** | |
* Instantiate and invoke all registered BeanFactoryPostProcessor beans, | |
* respecting explicit order if given. | |
* <p>Must be called before singleton instantiation. | |
*/ | |
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())); | |
} | |
} |
点进去看看
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<>(); | |
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. | |
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. | |
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<>(); | |
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<>(); | |
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();} |
点进去 invokeBeanFactoryPostProcessors 办法
/** | |
* Invoke the given BeanFactoryPostProcessor beans. | |
*/ | |
private static void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {for (BeanFactoryPostProcessor postProcessor : postProcessors) {postProcessor.postProcessBeanFactory(beanFactory); | |
} | |
} |
点击 postProcessBeanFactory(beanFactory); 找到实现类
@Override | |
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {int factoryId = System.identityHashCode(beanFactory); | |
if (this.factoriesPostProcessed.contains(factoryId)) { | |
throw new IllegalStateException("postProcessBeanFactory already called on this post-processor against" + beanFactory); | |
} | |
this.factoriesPostProcessed.add(factoryId); | |
if (!this.registriesPostProcessed.contains(factoryId)) { | |
// BeanDefinitionRegistryPostProcessor hook apparently not supported... | |
// Simply call processConfigurationClasses lazily at this point then. | |
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory); | |
} | |
enhanceConfigurationClasses(beanFactory); | |
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory)); | |
} |
点击 processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory); 办法找到
// 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); |
持续找 parse 办法, 找到 ConfigurationClassParser 类这个办法,接着找
@Nullable | |
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) | |
throws IOException { |
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), true); | |
// 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); | |
} | |
} | |
// Process individual @Bean methods | |
Set<MethodMetadata> 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; |
咱们找到 processImports 的解决中央
this.importStack.push(configClass); | |
try {for (SourceClass candidate : importCandidates) {if (candidate.isAssignable(ImportSelector.class)) { | |
// Candidate class is an ImportSelector -> delegate to it to determine imports | |
Class<?> candidateClass = candidate.loadClass(); | |
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class); | |
ParserStrategyUtils.invokeAwareMethods(selector, this.environment, this.resourceLoader, this.registry); | |
if (selector instanceof DeferredImportSelector) {this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector); | |
} | |
else {String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata()); | |
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames); | |
processImports(configClass, currentSourceClass, importSourceClasses, false); | |
} | |
} | |
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) { | |
// Candidate class is an ImportBeanDefinitionRegistrar -> | |
// delegate to it to register additional bean definitions | |
Class<?> candidateClass = candidate.loadClass(); | |
ImportBeanDefinitionRegistrar registrar = | |
BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class); | |
ParserStrategyUtils.invokeAwareMethods(registrar, this.environment, this.resourceLoader, this.registry); | |
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata()); | |
} | |
else { | |
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar -> | |
// process it as an @Configuration class | |
this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName()); | |
processConfigurationClass(candidate.asConfigClass(configClass)); | |
} | |
} | |
} |
ImportSelector 接口解决的中央,主动配置内部 bean 的办法 | |
接下来,看 registerBeanPostProcessors(beanFactory); 注册 bean 处理器工厂 | |
而后,看 onRefresh 办法 |
@Override | |
protected void onRefresh() {super.onRefresh(); | |
try {createWebServer(); | |
} | |
catch (Throwable ex) {throw new ApplicationContextException("Unable to start web server", ex); | |
} | |
} |
在这里创立 web 容器 | |
实现刷新,利用启动实现,还有细节结下来在细说。 |
有问题,请留言!集体博客地址