Spring boot基本使用及 stater机制原理_踩踩踩从踩的博客-CSDN博客
前面文章对于springboot得基本使用以及stater机制 以及autoconfig 做了一个解读,如何手写一个starter的包,对于 自动装配 解读,有了个大概的思维;这篇文章继续讲解SpringBoot的核心源码 ,然后深入的解析整个Springboot怎么快速的构建项目 并管理我们的依赖jar包等等。
@SpringBootApplication public class DeviceManagerApplication extends SpringBootServletInitializer {  	public static void main(String[] args) { 		SpringApplication.run(DeviceManagerApplication.class, args); 	}  	@Override 	protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { 		return builder.sources(DeviceManagerApplication.class); 	}  }

对于springboot 只需要运行run方法就可以将我们的程序给运行起来。
/** 	 * Static helper that can be used to run a {@link SpringApplication} from the 	 * specified source using default settings. 	 * @param primarySource the primary source to load 	 * @param args the application arguments (usually passed from a Java main method) 	 * @return the running {@link ApplicationContext} 	 */ 	public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) { 		return run(new Class<?>[] { primarySource }, args); 	}
该类,该类可用于从Java main引导和启动Spring应用程序方法。默认情况下,类将执行以下步骤来引导申请:
下面的步骤 核心逻辑 就是 创建 applicationcontext 实例、
并且 注册 CommandLinePropertySource
激活 CommandLineRunner 这个接口 用于指示当bean包含在 一个{@link SpringApplication}。可以定义多个{@link CommandLineRunner}bean 在同一个应用程序上下文中,可以使用{@link ordered} 接口或{@link Order@Order}注释。 也就是说可以 查看当前springapplication创建了那些bean.




/**一:注释上的重要信息: 1、primary sources:application context从primarySource加载beans  	2、创建的SpringApplication实例在调用它的run(String...)方法前,可对其进行定制化设置 可以进行哪些设置?看类中提供的public方法。 	* 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;  		// 1、一定要指定primarySources  		Assert.notNull(primarySources, "PrimarySources must not be null"); 		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));  		// 2、deduce(推断)web类型(servlet、reactive、NoWeb)  		this.webApplicationType = WebApplicationType.deduceFromClasspath();  		// 3、从META-INF/spring.factories中获取 		ApplicationContextInitializer setInitializers((Collection)  		getSpringFactoriesInstances( ApplicationContextInitializer.class));  		// 4、从META-INF/spring.factories中获取 		ApplicationListener setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));  		// 5、推断执行的main方法的定义类 this.mainApplicationClass = deduceMainApplicationClass();  	}webApplicationType 探测分配 是什么类型的 项目 ,其实是很简单的。 主要是判断 是否存在 父类


创建获取实例, 将监听器都放进去就可以了。
在初始化的时候会去调用

以及ApplicationListener 是作为监听器存在的。
/** 一:注释上的重要信息: 运行Spring application,创建并刷新一个 ApplicationContext    * 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) {  	// 二、方法中的逻辑:    	// 1 StopWatch开启计时  	StopWatch stopWatch = new StopWatch();  	stopWatch.start();  	ConfigurableApplicationContext context = null;  Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<> ();  	// 这是设置系统属性java.awt.headless,请百度了解 java.awt.headless的用途。 	configureHeadlessProperty();  	// 2、获取到 META-INF/spring.factories中配置的SpringApplicationRunListener  	// 疑问:又出一个Listener,这个SpringApplicationRunListener是监听什么的? 	// 通过它的接口定义、注释了解它的用途  	SpringApplicationRunListeners listeners = getRunListeners(args);  	// 这里就调用它的starting()  	listeners.starting(); 	try { 		// 命令行参数包装为了ApplicationArguments  		ApplicationArguments applicationArguments = new DefaultApplicationArguments( args);  		// 3、准备好了Environment,此刻Environment中都有哪些配置参数了? 		ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);  		configureIgnoreBeanInfo(environment);  		// 4、打印springboot LOGo图标  		Banner printedBanner = printBanner(environment);  		// 5、创建ApplicationContext context = createApplicationContext(); 		// 6、获取到 META-INF/spring.factories中配置的SpringBootExceptionReporter  		exceptionReporters = getSpringFactoriesInstances( SpringBootExceptionReporter.class, new Class[] {  		     ConfigurableApplicationContext.class }, context);  	     // 7、准备ApplicationContext  		 prepareContext(context, environment, listeners, applicationArguments, printedBanner);  		 // 8、刷新ApplicationContext  		 refreshContext(context);  		 afterRefresh(context, applicationArguments);  		 stopWatch.stop();  		 if (this.logStartupInfo) {  		     new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch);  		}//  		9、发布started事件 listeners.started(context); 		// 10、执行所有的Runners  		callRunners(context, applicationArguments);  	}catch (Throwable ex) {  	   handleRunFailure(context, ex, exceptionReporters, listeners);  	   throw new IllegalStateException(ex);     }     try { 	// 11、发布running中事件  	listeners.running(context);       }catch (Throwable ex) {  	   handleRunFailure(context, ex, exceptionReporters, null);  	   throw new IllegalStateException(ex);  	 } 	// 12、返回ok的ConfigurableApplicationContext return context;  	}configureHeadlessProperty 方法 该方法只做了一件事:设置了一个名为java.awt.headless的系统属性
	private void configureHeadlessProperty() { 		System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, 				System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless))); 	}SpringApplicationRunListeners 返回的所有 SpringApplicationRunListener 监听器 , 这里面就是 监听 它失败 等等状态。
	private SpringApplicationRunListeners getRunListeners(String[] args) { 		Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class }; 		return new SpringApplicationRunListeners(logger, 				getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args), 				this.applicationStartup); 	}
准备参数 DefaultApplicationArguments 本身需要处理

触发RunListener环境准备完成回调

根据类型加载 不同的参数。


ConfigurationPropertySources

包括各种 的配置启用的profiles 也可以指定 profiles 所以可以取出来做处理。


环境上准备 就有的这个。 参数配置


这里面就是 加载的配置参数。

会将事件给发布出来。


完整的加载过程。
 


在新版本中是添加




这里最终调用 的applicationcontext. refresh方法。

这个加载是整个 创建基础。
// 3、从META-INF/spring.factories中获取ApplicationContextInitializer  setInitializers((Collection) getSpringFactoriesInstances( ApplicationContextInitializer.class));这个方法 是可以加载 spring.factories
但是对于 EnableAutoconfiguration 的加载 是在那里去加载的,暂时不知道。


public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {}




public class AnnotationConfigServletWebServerApplicationContextextends ServletWebServerApplicationContext implements AnnotationConfigRegistry {}

@Override 	public WebServer getWebServer(ServletContextInitializer... initializers) { 		if (this.disableMBeanRegistry) { 			Registry.disableRegistry(); 		} 		Tomcat tomcat = new Tomcat(); 		File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat"); 		tomcat.setBaseDir(baseDir.getAbsolutePath()); 		Connector connector = new Connector(this.protocol); 		connector.setThrowOnFailure(true); 		tomcat.getService().addConnector(connector); 		customizeConnector(connector); 		tomcat.setConnector(connector); 		tomcat.getHost().setAutoDeploy(false); 		configureEngine(tomcat.getEngine()); 		for (Connector additionalConnector : this.additionalTomcatConnectors) { 			tomcat.getService().addConnector(additionalConnector); 		} 		prepareContext(tomcat.getHost(), initializers); 		return getTomcatWebServer(tomcat); 	}