说在前面
前期回顾
sharding-jdbc源码解析 更新完毕
spring源码解析 更新完毕
spring-mvc源码解析 更新完毕
spring-tx源码解析 更新完毕
spring-boot源码解析 更新完毕
rocketmq源码解析 更新完毕
dubbbo源码解析 更新完毕
netty源码解析 更新完毕
spring源码架构更新完毕
spring-mvc源码架构更新完毕
springboot源码架构更新中
github https://github.com/tianheframe
sharding-jdbc源码解析 更新完毕
rocketmq源码解析 更新完毕
seata 源码解析 更新完毕
dubbo 源码解析 更新完毕
netty 源码解析 更新完毕
源码解析

org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer 配置错误的ApplicationContextInitializer实现
@Override public void initialize(ConfigurableApplicationContext context) { context.addBeanFactoryPostProcessor( new ConfigurationWarningsPostProcessor(getChecks())); }
添加ConfigurationWarningsPostProcessor,获得检查项org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer#getChecks
protected Check[] getChecks() { return new Check[] { new ComponentScanPackageCheck() }; }
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer.ComponentScanPackageCheck
static { Set<String> packages = new HashSet<String>();// 默认会扫描org.springframework下所有的包 packages.add("org.springframework"); packages.add("org"); PROBLEM_PACKAGES = Collections.unmodifiableSet(packages); }
检查指定的包
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer.ConfigurationWarningsPostProcessor实现org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor接口。
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { }
获得BeanFactory参数,可以对BeanFactory中的BeanDefinition进行处理
@Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { for (Check check : this.checks) { String message = check.getWarning(registry); if (StringUtils.hasLength(message)) { warn(message); } } }
确认检查信息,发出警告
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer.ComponentScanPackageCheck
@Override public String getWarning(BeanDefinitionRegistry registry) { Set<String> scannedPackages = getComponentScanningPackages(registry); List<String> problematicPackages = getProblematicPackages(scannedPackages); if (problematicPackages.isEmpty()) { return null; } return "Your ApplicationContext is unlikely to " + "start due to a @ComponentScan of " + StringUtils.collectionToDelimitedString(problematicPackages, ", ") + "."; }
获得@ComponentScan指定的包,匹配spring的包,如果包含报错
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer.ComponentScanPackageCheck#getComponentScanningPackages 获得要扫描的包
protected Set<String> getComponentScanningPackages( BeanDefinitionRegistry registry) { Set<String> packages = new LinkedHashSet<String>();// 获得BeanFactory中所有的BeanDefinition名称 String[] names = registry.getBeanDefinitionNames(); for (String name : names) {// 获取指定名称的BeanDefinition BeanDefinition definition = registry.getBeanDefinition(name); if (definition instanceof AnnotatedBeanDefinition) { AnnotatedBeanDefinition annotatedDefinition = (AnnotatedBeanDefinition) definition;// 添加AnnotatedBeanDefinition指定的包名 addComponentScanningPackages(packages, annotatedDefinition.getMetadata()); } } return packages; }
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer.ComponentScanPackageCheck#addComponentScanningPackages 添加@ComponentScan指定的包
private void addComponentScanningPackages(Set packages, AnnotationMetadata metadata) {// 获取@ComponentScan属性 AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata .getAnnotationAttributes(ComponentScan.class.getName(), true)); if (attributes != null) { addPackages(packages, attributes.getStringArray("value")); addPackages(packages, attributes.getStringArray("basePackages"));// 类所在的包 addClasses(packages, attributes.getStringArray("basePackageClasses"));// 如果都没有指定添加元数据中指定的包名 if (packages.isEmpty()) { packages.add(ClassUtils.getPackageName(metadata.getClassName())); } } }
org.springframework.boot.web.support.ServletContextApplicationContextInitializer 设置servletContext的ApplicationContextInitializer
private final ServletContext servletContext;
servletContext
@Override public void initialize(ConfigurableWebApplicationContext applicationContext) { applicationContext.setServletContext(this.servletContext); if (this.addApplicationContextAttribute) { this.servletContext.setAttribute( WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, applicationContext); } }
设置ApplicationContext的servletContext
org.springframework.boot.builder.ParentContextApplicationContextInitializer 用于设置父上下文的ApplicationContextInitializer。还发布ParentContextApplicationContextInitializer。当上下文被刷新时,ParentContextAvailableEvent向其他侦听器发出信号,表明上下文可用并具有父上下文。
private final ApplicationContext parent;
ApplicationContext
@Override public void onApplicationEvent(ContextRefreshedEvent event) { ApplicationContext context = event.getApplicationContext(); if (context instanceof ConfigurableApplicationContext && context == event.getSource()) { context.publishEvent(new ParentContextAvailableEvent( (ConfigurableApplicationContext) context)); } } }
发布ApplicationContext事件
org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer 为嵌入servletcontainer服务器实际监听的端口设置环境属性。local.server财产”。port”可以直接使用@Value注入到测试中,也可以通过环境获得。如果EmbeddedWebApplicationContext有一个名称空间集,它将用于构造属性名。例如,“management”执行器上下文将具有属性名称“local.management.port”。属性将自动传播到任何父上下文。
@Override public void initialize(ConfigurableApplicationContext applicationContext) { applicationContext.addApplicationListener( new ApplicationListener() { @Override public void onApplicationEvent( EmbeddedServletContainerInitializedEvent event) { ServerPortInfoApplicationContextInitializer.this .onApplicationEvent(event); } }); }
添加serverPort相关的ApplicationContextInitializer
org.springframework.boot.context.config.DelegatingApplicationContextInitializer 将委托给在context.initializer下指定的其他初始化器的ApplicationContextInitializer。类环境属性。
@Override public void initialize(ConfigurableApplicationContext context) { ConfigurableEnvironment environment = context.getEnvironment(); List> initializerClasses = getInitializerClasses(environment); if (!initializerClasses.isEmpty()) { applyInitializerClasses(context, initializerClasses); } }
加载配置的初始化类,org.springframework.boot.context.config.DelegatingApplicationContextInitializer#getInitializerClasses 从配置文件中加载context.initializer.classes属性指定的初始化类
private List> getInitializerClasses(ConfigurableEnvironment env) {// 从配置文件中加载初始化类context.initializer.classes String classNames = env.getProperty(PROPERTY_NAME); List> classes = new ArrayList>(); if (StringUtils.hasLength(classNames)) { for (String className : StringUtils.tokenizeToStringArray(classNames, ",")) { classes.add(getInitializerClass(className)); } } return classes; }
private void applyInitializerClasses(ConfigurableApplicationContext context, List> initializerClasses) { Class> contextClass = context.getClass(); List> initializers = new ArrayList>(); for (Class> initializerClass : initializerClasses) {// 初始化初始化器 initializers.add(instantiateInitializer(contextClass, initializerClass)); } applyInitializers(context, initializers); }
初始化初始化的类并执行,org.springframework.boot.context.config.DelegatingApplicationContextInitializer#instantiateInitializer初始化初始化类
private ApplicationContextInitializer> instantiateInitializer(Class> contextClass, Class> initializerClass) { Class> requireContextClass = GenericTypeResolver.resolveTypeArgument( initializerClass, ApplicationContextInitializer.class); Assert.isAssignable(requireContextClass, contextClass, String.format( "Could not add context initializer [%s]" + " as its generic parameter [%s] is not assignable " + "from the type of application context used by this " + "context loader [%s]: ", initializerClass.getName(), requireContextClass.getName(), contextClass.getName())); return (ApplicationContextInitializer>) BeanUtils .instantiateClass(initializerClass); }
org.springframework.boot.context.config.DelegatingApplicationContextInitializer#applyInitializers执行org.springframework.context.ApplicationContextInitializer#initialize方法
private void applyInitializers(ConfigurableApplicationContext context, List> initializers) { Collections.sort(initializers, new AnnotationAwareOrderComparator()); for (ApplicationContextInitializer initializer : initializers) {// 执行初始化器的初始化方法 initializer.initialize(context); } }
org.springframework.boot.context.ContextIdApplicationContextInitializer 设置Spring ApplicationContext ID的ApplicationContextInitializer。
org.springframework.boot.web.support.SpringBootServletInitializer 实现了org.springframework.web.WebApplicationInitializer接口,一个固执己见的WebApplicationInitializer,用于从传统的WAR部署运行spring应用程序。将Servlet、Filter和ServletContextInitializer bean从应用程序上下文绑定到Servlet容器。要配置应用程序,要么重写configure(SpringApplicationBuilder)方法(调用SpringApplicationBuilder.sources(Object…)),要么将初始化器本身设置为@Configuration。如果您将SpringBootServletInitializer与其他webapplicationinitialalizer结合使用,您可能还想添加一个@Ordered注释来配置特定的启动顺序。注意,只有在构建和部署war文件时才需要WebApplicationInitializer。如果您喜欢运行嵌入式容器,那么您根本不需要这个。
@Override public void onStartup(ServletContext servletContext) throws ServletException { // Logger initialization is deferred in case a ordered // LogServletContextInitializer is being used this.logger = LogFactory.getLog(getClass());// 创建web应用上下文 WebApplicationContext rootAppContext = createRootApplicationContext( servletContext); if (rootAppContext != null) { servletContext.addListener(new ContextLoaderListener(rootAppContext) { @Override public void contextInitialized(ServletContextEvent event) { // no-op because the application context is already initialized } }); } else { this.logger.debug("No ContextLoaderListener registered, as " + "createRootApplicationContext() did not " + "return an application context"); } }
创建WebApplicationContext,启动SpringApplication程序,org.springframework.boot.web.support.SpringBootServletInitializer#createRootApplicationContext 创建WebApplicationContext
protected WebApplicationContext createRootApplicationContext( ServletContext servletContext) {// 创建SpringApplicationBuilder SpringApplicationBuilder builder = createSpringApplicationBuilder();// 设置application启动的main方法所在类 builder.main(getClass());// 是否存在web应用上下文 ApplicationContext parent = getExistingRootWebApplicationContext(servletContext); if (parent != null) { this.logger.info("Root context already created (using as parent)."); servletContext.setAttribute( WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, null);// 添加初始化器 builder.initializers(new ParentContextApplicationContextInitializer(parent)); } builder.initializers( new ServletContextApplicationContextInitializer(servletContext));// 设置web上下文的类 AnnotationConfigEmbeddedWebApplicationContext builder.contextClass(AnnotationConfigEmbeddedWebApplicationContext.class); builder = configure(builder);// 添加监听器 builder.listeners(new WebEnvironmentPropertySourceInitializer(servletContext));// 构建spring应用 SpringApplication application = builder.build();// 找到有@Configuration注解的类 if (application.getSources().isEmpty() && AnnotationUtils .findAnnotation(getClass(), Configuration.class) != null) { application.getSources().add(getClass()); } Assert.state(!application.getSources().isEmpty(), "No SpringApplication sources have been defined. Either override the " + "configure method or add an @Configuration annotation"); // Ensure error pages are registered if (this.registerErrorPageFilter) { application.getSources().add(ErrorPageFilterConfiguration.class); }// 启动spring boot应用程序 return run(application); }
org.springframework.boot.web.support.SpringBootServletInitializer#run 运行SpringApplication程序
protected WebApplicationContext run(SpringApplication application) { return (WebApplicationContext) application.run(); }
org.springframework.boot.SpringApplication#run(java.lang.String...)
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; FailureAnalyzers analyzers = null; configureHeadlessProperty();// 初始化SpringApplicationRunListener -》 SpringApplicationRunListeners listeners = getRunListeners(args);// 执行EventPublishingRunListener监听器,广播应用启动事件 listeners.starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments( args);// 准备环境 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);// 打印banner Banner printedBanner = printBanner(environment);// 初始化spring上下文 -》 context = createApplicationContext(); analyzers = new FailureAnalyzers(context);// 准备spring上下文 -》 prepareContext(context, environment, listeners, applicationArguments, printedBanner);// 刷新spring上下文 -》 refreshContext(context);// spring上下文初始化完毕加载其他applicationRunner afterRefresh(context, applicationArguments);// 执行监听器spring加载完成事件 listeners.finished(context, null); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } return context; } catch (Throwable ex) { handleRunFailure(context, listeners, analyzers, ex); throw new IllegalStateException(ex); } }
这个方法前面介绍过了
private ApplicationContext getExistingRootWebApplicationContext( ServletContext servletContext) { Object context = servletContext.getAttribute( WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); if (context instanceof ApplicationContext) { return (ApplicationContext) context; } return null; }
获得ApplicationContext
说在最后
本次解析仅代表个人观点,仅供参考。
扫码进入技术微信群

钉钉技术群

qq技术群
