引言
  1. 在引入 Spring Boot 框架之后,省去了 xml 文件配置可以理解为注解体系的不断完善,但省去的依赖的管理, Spring Boot 框架是如何做到的?
  2. 我们返回启动类,观察其中代码

这其中有两个关键的地方值得研究

  1. 注解:@SpringBootApplication
  2. run方法:SpringApplication.run()
对于注解 @SpringBootApplication
  1. 查看 @SpringBootApplication 源码

这里重点的注解有3个

  1. @SpringBootConfiguration
  2. @EnableAutoConfiguration
  3. @ComponentScan
  1. 查看 @SpringBootConfiguration 源码

解读:

  1. 可以看到,这个注解上面,又有一个 @Configuration 注解
  2. 通过上面的注释了解到:这个注解的作用就是声明当前类是一个配置类,然后 Spring 会自动扫描到添加了 @Configuration 的类,并且读取其中的配置信息
  3. 而 @SpringBootConfiguration 是来声明当前类是SpringBoot应用的配置类,项目中只能有一个,所以一般我们无需自己添加
  1. 查看 @EnableAutoConfiguration 源码

解读

  1. 插入一段官方说明:The second class-level annotation is @EnableAutoConfiguration. This annotation tells Spring Boot to “guess” how you want to configure Spring, based on the jar dependencies that you have added. Since spring-boot-starter-web added Tomcat and Spring MVC, the auto-configuration assumes that you are developing a web application and sets up Spring accordingly.
  2. 简单翻译为:第二级的注解@EnableAutoConfiguration,告诉SpringBoot基于你所添加的依赖,去“猜测”你想要如何配置Spring。比如我们引入了spring-boot-starter-web,而这个启动器中帮我们添加了tomcat、SpringMVC的依赖。此时自动配置就知道你是要开发一个web应用,所以就帮你完成了web及SpringMVC的默认配置了
  3. 结合源码内注释,大概得出结论,Spring Boot 内部对大量的第三方库及 Spring 内库进行了默认配置,并且会根据我们在创建项目时候的风格,是否引入了对应库的依赖等来判断哪些配置可能会被使用到,这些默认配置就会生效
  4. 所以,我们使用SpringBoot构建一个项目,只需要引入所需框架的依赖,配置就可以交给SpringBoot处理了,若你不希望使用SpringBoot的默认配置,它也提供了自定义配置的入口
  1. 查看 @ComponentScan 源码

解读:

  1. 注释大概意思:配置组件扫描的指令。提供了类似与< context:component-scan >标签的作用,通过 basePackageClasses 或者 basePackages 属性来指定要扫描的包。如果没有指定这些属性,那么将从声明这个注解的类所在的包开始,扫描包及子包
  2. 我们的@SpringBootApplication注解声明的类就是main函数所在的启动类,因此扫描的包是该类所在包及其子包
  3. 因此,启动类在项目目录结构中,一般都会处于较浅层的位置,以便于扫描
对于 SpringApplication.run() 方法
  1. 点击查看源码中方法
/**
  * 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);
 	
 	//发布ApplicationStartingEvent
 	
 	listeners.starting();
 	try {
 	
 		//装配参数和环境
 		
 		ApplicationArguments applicationArguments = new DefaultApplicationArguments(
 				args);
 				
 		//发布ApplicationEnvironmentPreparedEvent
 		
 		ConfigurableEnvironment environment = prepareEnvironment(listeners,
 				applicationArguments);
 		configureIgnoreBeanInfo(environment);
 		Banner printedBanner = printBanner(environment);
 		
 		//创建ApplicationContext,并装配
 		
 		context = createApplicationContext();
 		exceptionReporters = getSpringFactoriesInstances(
 				SpringBootExceptionReporter.class,
 				new Class[] { ConfigurableApplicationContext.class }, context);
 				
 		//发布ApplicationPreparedEvent
 		
 		prepareContext(context, environment, listeners, applicationArguments,
 				printedBanner);
 		refreshContext(context);
 		afterRefresh(context, applicationArguments);
 		stopWatch.stop();
 		if (this.logStartupInfo) {
 			new StartupInfoLogger(this.mainApplicationClass)
 					.logStarted(getApplicationLog(), stopWatch);
 		}
 		
 		//发布ApplicationStartedEvent
 		
 		listeners.started(context);

 		//执行Spring中@Bean下的一些操作,如静态方法等
 		
 		callRunners(context, applicationArguments);
 	}
 	catch (Throwable ex) {
 		handleRunFailure(context, ex, exceptionReporters, listeners);
 		throw new IllegalStateException(ex);
 	}

 	try {
 	
 		//发布ApplicationReadyEvent
 		
 		listeners.running(context);
 	}
 	catch (Throwable ex) {
 		handleRunFailure(context, ex, exceptionReporters, null);
 		throw new IllegalStateException(ex);
 	}
 	return context;
 }
  1. 观察源码中执行的步骤大概分为
  1. 初始化监听器
  2. 发布ApplicationStartingEvent
  3. 装配参数和环境
  4. 发布ApplicationEnvironmentPreparedEvent
  5. 创建ApplicationContext,并装配
  6. 发布ApplicationPreparedEvent
  7. 发布ApplicationStartedEvent
  8. 执行Spring中@Bean下的一些操作,如静态方法等
  9. 发布ApplicationReadyEvent