赞
踩
SpringMVC的源码解析(精品)
Spring6的源码解析(精品)
SpringBoot3框架(精品)
MyBatis框架(精品)
MyBatis-Plus
SpringDataJPA
SpringCloudNetflix
SpringCloudAlibaba(精品)
Shiro
SpringSecurity
java的LOG日志框架
Activiti(敬请期待)
JDK8新特性
JDK9新特性
JDK10新特性
JDK11新特性
JDK12新特性
JDK13新特性
JDK14新特性
JDK15新特性
JDK16新特性
JDK17新特性
JDK18新特性
JDK19新特性
JDK20新特性
JDK21新特性
其他技术文章传送门入口
由于面试问到的比较多,而且做java开发这块还是需要真正掌握的。
现有笔记尚硅谷雷锋阳老师的:SpringBoot3全栈指南,是我目前见过的最好笔记了。
参考视频尚硅谷雷锋阳老师的:SpringBoot零基础教程,面试&加薪必会,视频是24小时31分钟的高质量教程。
参考代码:https://gitee.com/leifengyang/spring-boot-3
本文以SpringBoot3.1.2中Spring对应版本是6.0.11为例。
下面文章不定期更新中…
最经典的20个Spring Boot面试题,95%以上会被问到,不服来战
10和11行代码的区别,10行传了args参数,java -jar xxx.jar --k1=v1这种的时候,就是有效果的,否则像11行那样,是没有效果的。
我们来看一个SpringBoot3的启动类案例,并跟着这个案例深入
@SpringBootApplication
public class JdkNewFeaturesDemoApplication {
public static void main(String[] args) {
SpringApplication.run(JdkNewFeaturesDemoApplication.class, args);// 断点进入run方法
}
}
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);// 断点进入run方法
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);// 分两部分,断点进入第一部分new,断点进入第二部分run
}
ConfigurableApplicationContext 类是容器上下文,但是不是最终容器上下文,SpringApplication非Spring容器上下文。
一般最终Spring容器上下文是AnnotationConfigServletWebServerApplicationContext。
我们断点进入第一部分new的代码
public SpringApplication(Class<?>... primarySources) { this(null, primarySources); } /** * Create a new {@link SpringApplication} instance. The application context will load * beans from the specified primary sources (see {@link SpringApplication class-level} * documentation for details). The instance can be customized before calling * {@link #run(String...)}. * @param resourceLoader the resource loader to use * @param primarySources the primary bean sources * @see #run(Class, String[]) * @see #setSources(Set) */ @SuppressWarnings({ "unchecked", "rawtypes" }) public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { this.resourceLoader = resourceLoader;// 资源加载器 Assert.notNull(primarySources, "PrimarySources must not be null"); this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));// primarySources启动类 this.webApplicationType = WebApplicationType.deduceFromClasspath();// 判断web的上下文是servlet上下文还是reactive上下文,reactive是响应式编程(webflux),当然SpringBoot默认是servlet this.bootstrapRegistryInitializers = new ArrayList<>( getSpringFactoriesInstances(BootstrapRegistryInitializer.class)); setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));//(断点进入设置初始化器) 设置初始化器,就是将实现了ApplicationContextInitializer接口的实现类实例化并缓存一下,这边会加载到META-INF/spring.factories(该文件就是自动装配。主要是接口和实现类的对应,一个接口有多个实现类值,Key-Values的对应) setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));// 设置监听器,将实现了ApplicationListener接口的实现类实例化 this.mainApplicationClass = deduceMainApplicationClass();// 调用main方法的类返回出来赋值到这里,目的是解析这个类以及类上的注解。 }
我们断点进入设置初始化器
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class))
private <T> List<T> getSpringFactoriesInstances(Class<T> type) { return getSpringFactoriesInstances(type, null);// 断点持续进入 } private <T> List<T> getSpringFactoriesInstances(Class<T> type, ArgumentResolver argumentResolver) { return SpringFactoriesLoader.forDefaultResourceLocation(getClassLoader()).load(type, argumentResolver); // 第一部分forDefaultResourceLocation这边会加载到META-INF/spring.factories(该文件就是自动装配。主要是接口和实现类的对应,一个接口有多个实现类值,Key-Values的对应) // 第二部分load,断点持续进入 } public <T> List<T> load(Class<T> factoryType, @Nullable ArgumentResolver argumentResolver, @Nullable FailureHandler failureHandler) { Assert.notNull(factoryType, "'factoryType' must not be null"); List<String> implementationNames = loadFactoryNames(factoryType);// 加载到对应类的实现名字,也就是实现了ApplicationContextInitializer接口的实现类 logger.trace(LogMessage.format("Loaded [%s] names: %s", factoryType.getName(), implementationNames)); List<T> result = new ArrayList<>(implementationNames.size()); FailureHandler failureHandlerToUse = (failureHandler != null) ? failureHandler : THROWING_FAILURE_HANDLER; for (String implementationName : implementationNames) { // 将这些实现名字做一个实例化 T factory = instantiateFactory(implementationName, factoryType, argumentResolver, failureHandlerToUse); if (factory != null) { result.add(factory); } } AnnotationAwareOrderComparator.sort(result); return result;// 这类比一个缓存,以后获取的时候方便 }
我们返回到开始,断点进入第二部分run的代码
public ConfigurableApplicationContext run(String... args) { long startTime = System.nanoTime(); DefaultBootstrapContext bootstrapContext = createBootstrapContext();// 创建一个启动上下文,非Spring容器上下文,做一些启动方面相关的处理,只是在boot工程启动时间的临时上下文,内置多播器 ConfigurableApplicationContext context = null; // 根据系统变量java.awt.headless的值来设置java.headless.mode,缺省值是true, // 在系统可能缺少显示设备、键盘或鼠标这些外设的情况下可以使用该模式。 // 默认为true,因为大部分的boot项目都不需要外设交互,一旦启动成功就不需要操作。 configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args);// 拿到一些监听器 listeners.starting(bootstrapContext, this.mainApplicationClass);// 监听器开始工作,发布ApplicationStartingEvent事件 try { ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 获取命令行参数 ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);// 准备环境 Banner printedBanner = printBanner(environment);// 打印banner // 【核心】创建一个Spring上下文,不执行refresh方法,一般最终Spring容器上下文是AnnotationConfigServletWebServerApplicationContext context = createApplicationContext();// 断点进入创建Spring容器上下文 context.setApplicationStartup(this.applicationStartup);// 设置记录步骤的记录器 // 这里会将一些早期事件注册给多播器,并发布一个事件 // 【核心】准备上下文 prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);// 断点进入准备上下文 // 【核心】刷新容器,真正执行了refresh方法 refreshContext(context);// 断点进入刷新容器 afterRefresh(context, applicationArguments);// 刷新后处理 Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup); } listeners.started(context, timeTakenToStartup);// 广播启动完成事件 callRunners(context, applicationArguments);// 执行所有的runner,runner机制,实现对应接口,在SpringBoot启动后能做一些初始化工作,比如Redis预热 } catch (Throwable ex) { if (ex instanceof AbandonedRunException) { throw ex; } handleRunFailure(context, ex, listeners); throw new IllegalStateException(ex); } try { if (context.isRunning()) { Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime); listeners.ready(context, timeTakenToReady); } } catch (Throwable ex) { if (ex instanceof AbandonedRunException) { throw ex; } handleRunFailure(context, ex, null); throw new IllegalStateException(ex); } return context; }
我们断点进入context = createApplicationContext();// 断点进入创建Spring容器上下文
protected ConfigurableApplicationContext createApplicationContext() { return this.applicationContextFactory.create(this.webApplicationType);// DefaultApplicationContextFactory是成员变量就赋值好的默认上下文工厂,webApplicationType类型是SERVLET(根据配置决定的) } // 断点进入DefaultApplicationContextFactory的create方法 // 实际上走的ServletWebServerApplicationContextFactory的create方法(SpringBoot默认是servlet,所以一般是走这个实现类的create方法) @Override public ConfigurableApplicationContext create(WebApplicationType webApplicationType) { try { return getFromSpringFactories(webApplicationType, ApplicationContextFactory::create, this::createDefaultApplicationContext);// 断点进入getFromSpringFactories } catch (Exception ex) { throw new IllegalStateException("Unable create a default ApplicationContext instance, " + "you may need a custom ApplicationContextFactory", ex); } } // 断点进入getFromSpringFactories方法 private <T> T getFromSpringFactories(WebApplicationType webApplicationType, BiFunction<ApplicationContextFactory, WebApplicationType, T> action, Supplier<T> defaultResult) { // 循环ApplicationContextFactory的实现类,一般有三个,在spring.factories中可以看到(不同jar包这个文件内容不一样) // DefaultApplicationContextFactory、ReactiveWebServerApplicationContextFactory、ServletWebServerApplicationContextFactory for (ApplicationContextFactory candidate : SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class, getClass().getClassLoader())) { T result = action.apply(candidate, webApplicationType);// 判断哪个工厂能满足条件,这边一般返回了子类,返回的就是最终的Spring容器上下文,比如SpringBoot默认是servlet而非reactive,返回的就是AnnotationConfigServletWebServerApplicationContext if (result != null) { return result; } } return (defaultResult != null) ? defaultResult.get() : null; }
我们返回到上一级ConfigurableApplicationContext的run方法代码中, 断点进入准备上下文
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { context.setEnvironment(environment);// 设置环境 postProcessApplicationContext(context);// 上下文的后置处理,设置了消息转化器 addAotGeneratedInitializerIfNecessary(this.initializers);// aot相关 applyInitializers(context);// 调用之前设置的初始化器,执行一些方法 listeners.contextPrepared(context);// ApplicationcontextInitializedEvent事件 bootstrapContext.close(context);// 关闭启动上下文 if (this.logStartupInfo) { logStartupInfo(context.getParent() == null); logStartupProfileInfo(context); } // Add boot specific singleton beans ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();// 从上下文拿到默认的bean工厂,下面给工厂设置一些参数 beanFactory.registerSingleton("springApplicationArguments", applicationArguments); if (printedBanner != null) { beanFactory.registerSingleton("springBootBanner", printedBanner); } if (beanFactory instanceof AbstractAutowireCapableBeanFactory autowireCapableBeanFactory) { autowireCapableBeanFactory.setAllowCircularReferences(this.allowCircularReferences);// 设置是否允许循环引用,默认是没有开启循环引用的。 if (beanFactory instanceof DefaultListableBeanFactory listableBeanFactory) { listableBeanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);// 设置BeanDefinition是否可以被覆盖,默认false没有开启。 } } if (this.lazyInitialization) { context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor()); } context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));// 添加一些BeanFactory的后置处理器,PropertySourceOrder是优先级高的那批后置处理器。 if (!AotDetector.useGeneratedArtifacts()) { // Load the sources Set<Object> sources = getAllSources();// 加载资源,BeanDefinition Assert.notEmpty(sources, "Sources must not be empty"); load(context, sources.toArray(new Object[0])); } listeners.contextLoaded(context);// 发布上下文加载相关的事件 }
我们返回到上一级ConfigurableApplicationContext的run方法代码中, 断点进入
refreshContext(context);// 断点进入刷新容器
private void refreshContext(ConfigurableApplicationContext context) { if (this.registerShutdownHook) { shutdownHook.registerApplicationContext(context);// shutdownHook是钩子 } refresh(context);// 断点持续进入 } protected void refresh(ConfigurableApplicationContext applicationContext) { applicationContext.refresh();// 断点持续进入 } // ServletWebServerApplicationContext的refresh方法(servlet进入这个) @Override public final void refresh() throws BeansException, IllegalStateException { try { super.refresh();// 就会调用到父类的AbstractApplicationContext的refresh方法,真正刷新。父类的refresh方法中预留的让子类调用的扩展点,有被SpringBoot重写。比如refresh方法里面的onRefresh方法,就被子类启动了tomcat。 } catch (RuntimeException ex) {// 抛异常,如果SpringBoot上下文启动失败 WebServer webServer = this.webServer;// 能获取到webServer if (webServer != null) { webServer.stop();// 会将webServer停止掉 } throw ex; } }
我们回到最开始,持续进入看@SpringBootApplication注解,可以看到重要的@EnableAutoConfiguration注解
@SpringBootApplication// 持续点进去
public class JdkNewFeaturesDemoApplication {
public static void main(String[] args) {
SpringApplication.run(JdkNewFeaturesDemoApplication.class, args);// 断点进入run方法
}
}
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class)// 点进去,引入一个Selector,这个Selector返回的字符串数组,里面所有的全限定名称bean都会加载到Spring容器中。 public @interface EnableAutoConfiguration { /** * Environment property that can be used to override when auto-configuration is * enabled. */ 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 {}; }
AutoConfigurationImportSelector点进去可以看到重要的selectImports方法
@Override public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } // 【核心】获取到自动装配的健值对 AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);// 断点进入 // 将键值对里面的Configurations拿到,返回字符串数组,进而加载到Spring容器中。 return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); } // 断点进入 protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return EMPTY_ENTRY; } // annotationMetadata就是启动类com.zt.JdkNewFeaturesDemoApplication相关的一些东西,是元数据 AnnotationAttributes attributes = getAttributes(annotationMetadata);// attributes为exclude和excludeName,后面主要用于排除一些bean // 【核心】获取候选的配置类,SpringBoot3.1.2版本有146个XxxAutoConfiguration自动装配配置类。 List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);// 断点进入 // 进行筛选去重过滤 configurations = removeDuplicates(configurations); Set<String> exclusions = getExclusions(annotationMetadata, attributes); checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = getConfigurationClassFilter().filter(configurations);// 最后得到25个 fireAutoConfigurationImportEvents(configurations, exclusions); return new AutoConfigurationEntry(configurations, exclusions);// key是25个List<String>,value是空的Set<String> } // 断点进入 protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { // 【核心】加载AutoConfiguration.class作为key的所有资源 List<String> configurations = ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader())// 断点进入 .getCandidates(); Assert.notEmpty(configurations, "No auto configuration classes found in " + "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you " + "are using a custom packaging, make sure that file is correct."); return configurations; }
断点进入
List configurations = ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader())
【核心】加载AutoConfiguration.class作为key的所有资源
// annotation这个就是AutoConfiguration.class public static ImportCandidates load(Class<?> annotation, ClassLoader classLoader) { Assert.notNull(annotation, "'annotation' must not be null"); ClassLoader classLoaderToUse = decideClassloader(classLoader); // 格式化LOCATION,格式化后的字符串为 // META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports // 这个imports文件就在自动装配spring-boot-autoconfigure的jar包里面,路径就是上面路径 // 里面是Spring支持的所有的自动装配相关的配置类,注意都是XxxAutoConfiguration配置类 String location = String.format(LOCATION, annotation.getName()); Enumeration<URL> urls = findUrlsInClasspath(classLoaderToUse, location); List<String> importCandidates = new ArrayList<>(); while (urls.hasMoreElements()) { URL url = urls.nextElement(); importCandidates.addAll(readCandidateConfigurations(url)); } return new ImportCandidates(importCandidates); }
难点:
SpringBoot3.1.2版本有146个XxxAutoConfiguration自动装配配置类是在Spring的refresh方法中哪一步加载进入的呢?
答案是refresh的12个方法中第5个方法:
方法5之前beanFactory对象的beanDefinitionMap属性只有6个,也就是有6个基本的BeanDefinition;
invokeBeanFactoryPostProcessors(beanFactory);// 5、执行BeanFactoryPostProcessor的方法;
方法5之后,beanDefinitionMap就有146个了。
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");// 记录每一步执行的工具类 // Prepare this context for refreshing. prepareRefresh();// 1、准备刷新容器上下文 // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 2、获取BeanFactory;默认实现是DefaultListableBeanFactory,在创建容器的时候创建的,beanFactory 里面有个beanDefinitionMap属性,存放BeanDefinition。 // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory);// 3、BeanFactory的预准备工作(BeanFactory进行一些设置,比如context的类加载器,BeanPostProcessor和XXXAware自动装配等) try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory);// 4、BeanFactory准备工作完成后进行的后置处理工作(留给子类实现,空方法) StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process"); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory);// 5、执行BeanFactoryPostProcessor的方法; // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory);// 6、注册BeanPostProcessor(Bean的后置处理器),在创建bean的前后等执行 beanPostProcess.end(); // Initialize message source for this context. initMessageSource();// 7、初始化MessageSource组件(做国际化功能;消息绑定,消息解析); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // 8、初始化事件多播器 // Initialize other special beans in specific context subclasses. onRefresh();// 9、子类重写这个方法,在容器刷新的时候可以自定义逻辑;如创建Tomcat,Jetty等WEB服务器 // Check for listener beans and register them. registerListeners(); // 10、注册应用的监听器。就是注册实现了ApplicationListener接口的监听器bean,这些监听器是注册到ApplicationEventMulticaster中的 // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory);// 11、实例化所有的非懒加载单例bean(最最核心方法) // Last step: publish corresponding event. finishRefresh();// 12、完成context的刷新。主要是调用LifecycleProcessor的onRefresh()方法,并且发布事件(ContextRefreshedEvent) } 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(); contextRefresh.end(); } } }
一路判断invokeBeanFactoryPostProcessors(beanFactory)中哪一行代码导致的beanDefinitionMap突然变多,会发现
ConfigurationClassPostProcessor这个processor是优先级最高的被执行的processor(实现了PriorityOrdered接口)。
在我Spring6源码解析的文章中有详细的讲解。(见传送门)
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {
// for循环第一个就是ConfigurationClassPostProcessor
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
.tag("postProcessor", postProcessor::toString);
// ConfigurationClassPostProcessor类里面的postProcessBeanDefinitionRegistry方法执行后,
// 这里就将剩余的BeanDefinition(XxxAutoConfiguration)注册进入了,beanDefinitionMap就有146个了
// 有了XxxAutoConfiguration这些BeanDefinition,其余的通过条件判断注解等等条件,普通的BeanDefinition也就注册进去了
postProcessor.postProcessBeanDefinitionRegistry(registry);
postProcessBeanDefRegistry.end();
}
}
接下来就是看ConfigurationClassPostProcessor何时进入的容器,ConfigurationClassPostProcessor是在最初始的beanDefinitionMap的6个里面的。
接下来我们就要看SpringBoot的run方法来分析了
其中context = createApplicationContext();// 【核心】创建一个Spring上下文,不执行refresh方法
我们仔细回顾一下这一步
public ConfigurableApplicationContext run(String... args) { long startTime = System.nanoTime(); DefaultBootstrapContext bootstrapContext = createBootstrapContext();// 创建一个启动上下文,非Spring容器上下文,做一些启动方面相关的处理,只是在boot工程启动时间的临时上下文,内置多播器 ConfigurableApplicationContext context = null; // 根据系统变量java.awt.headless的值来设置java.headless.mode,缺省值是true, // 在系统可能缺少显示设备、键盘或鼠标这些外设的情况下可以使用该模式。 // 默认为true,因为大部分的boot项目都不需要外设交互,一旦启动成功就不需要操作。 configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args);// 拿到一些监听器 listeners.starting(bootstrapContext, this.mainApplicationClass);// 监听器开始工作,发布ApplicationStartingEvent事件 try { ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 获取命令行参数 ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);// 准备环境 Banner printedBanner = printBanner(environment);// 打印banner // 【核心】创建一个Spring上下文,不执行refresh方法,一般最终Spring容器上下文是AnnotationConfigServletWebServerApplicationContext context = createApplicationContext();// 断点进入创建Spring容器上下文 context.setApplicationStartup(this.applicationStartup);// 设置记录步骤的记录器 // 这里会将一些早期事件注册给多播器,并发布一个事件 // 【核心】准备上下文 prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);// 断点进入准备上下文 // 【核心】刷新容器,真正执行了refresh方法 refreshContext(context);// 断点进入刷新容器 afterRefresh(context, applicationArguments);// 刷新后处理 Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup); } listeners.started(context, timeTakenToStartup);// 广播启动完成事件 callRunners(context, applicationArguments);// 执行所有的runner,runner机制,实现对应接口,在SpringBoot启动后能做一些初始化工作,比如Redis预热 } catch (Throwable ex) { if (ex instanceof AbandonedRunException) { throw ex; } handleRunFailure(context, ex, listeners); throw new IllegalStateException(ex); } try { if (context.isRunning()) { Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime); listeners.ready(context, timeTakenToReady); } } catch (Throwable ex) { if (ex instanceof AbandonedRunException) { throw ex; } handleRunFailure(context, ex, null); throw new IllegalStateException(ex); } return context; }
我们断点进入context = createApplicationContext();// 断点进入创建Spring容器上下文
protected ConfigurableApplicationContext createApplicationContext() { return this.applicationContextFactory.create(this.webApplicationType);// DefaultApplicationContextFactory是成员变量就赋值好的默认上下文工厂,webApplicationType类型是SERVLET(根据配置决定的) } // 断点进入ServletWebServerApplicationContextFactory的create方法(SpringBoot默认是servlet,所以一般是走这个实现类的create方法) @Override public ConfigurableApplicationContext create(WebApplicationType webApplicationType) { return (webApplicationType != WebApplicationType.SERVLET) ? null : createContext(); } private ConfigurableApplicationContext createContext() { if (!AotDetector.useGeneratedArtifacts()) { // 【核心】构造这个最终Spring容器上下文的时候,创建了初始的beanDefinitionMap中的BeanDefinition return new AnnotationConfigServletWebServerApplicationContext();// 断点进入 } return new ServletWebServerApplicationContext(); }
我们断点进入
return new AnnotationConfigServletWebServerApplicationContext();
public AnnotationConfigServletWebServerApplicationContext() {
// 这边注册了5个
this.reader = new AnnotatedBeanDefinitionReader(this);// 断点进入
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
断点进入
this.reader = new AnnotatedBeanDefinitionReader(this);
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));// 点this断点进入
}
// 点this断点进入
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);// 条件计算器,做条件注解相关的一些工具
// 注册AnnotationConfig的处理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);// 断点进入
}
断点进入
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) { registerAnnotationConfigProcessors(registry, null); // 断点进入 } // 断点进入 // 主要注入了5个bean public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) { DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); if (beanFactory != null) { if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) { beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); } if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) { beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); } } Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);// BeanDefinition的持有者 // ConfigurationClassPostProcessor的注册 if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);// 转为BeanDefinition def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); } if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } // Check for Jakarta Annotations support, and if present add the CommonAnnotationBeanPostProcessor. if ((jakartaAnnotationsPresent || jsr250Present) && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)); } // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor. if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(); try { def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, AnnotationConfigUtils.class.getClassLoader())); } catch (ClassNotFoundException ex) { throw new IllegalStateException( "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex); } def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)); } if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME)); } if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME)); } return beanDefs; }
ConfigurationClassPostProcessor就是此时进入的容器。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。