Spring Boot对Spring应用的开发进行了简化,提供了模块化方式导入依赖的能力,可方便快捷地开发RESTful Web服务。简化了开发过程中大量XML配置以及复杂的依赖管理,让开发人员更加关注于业务逻辑。
Spring Boot内部提供了很多自动化配置的类,这些类会判断classpath中是否存在自己需要的那个类,如果存在则会自动配置相关的配置,否则就不会自动配置。如果我们需要使用一些框架,只需要加入依赖即可,这些依赖内部是没有代码的,只是一些对应框架需要的lib,有了这些lib就会触发自动化配置,于是就能使用框架了。而这些是如何实现的呢?学习下Spring Boot的内部原理可以帮助我们更好地掌握它。
开发任何一个Spring Boot项目,都会有一个启动类作为主程序入口,例如:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
main里面调用SpringApplication.run()启动整个spring-boot程序,该方法所在类需要使用@SpringBootApplication注解。
SpringBootApplication注解
SpringBootApplication主要包括三个注解,功能如下:
- @EnableAutoConfiguration:SpringBoot根据应用所声明的依赖来对Spring框架进行自动配置;
- @SpringBootConfiguration(内部为@Configuration):被标注的类等于在spring的XML配置文件中(applicationContext.xml),装配所有bean事务,提供了一个spring的上下文环境;
- @ComponentScan:组件扫描,可自动发现和装配Bean,默认扫描SpringApplication的run方法里的Booter.class所在的包路径下文件,所以最好将该启动类放到根包路径下。
在这3个注解中比较重要的是@EnableAutoConfiguration,它是借助@Import的帮助,将所有符合自动配置条件的bean定义加载到IoC容器。@Import其实就是用来导入一个或多个普通类(会被spring容器管理),或者配置类(配置类里的@Bean标记的类也会被spring容器管理)。
在@EnableAutoConfiguration中引入了@Import(EnableAutoConfigurationImportSelector.class),EnableAutoConfigurationImportSelector类使用了Spring Core包的SpringFactoriesLoader类的loadFactoryNamesof()方法。 SpringFactoriesLoader会查询META-INF/spring.factories文件中包含的JAR文件。 当找到spring.factories文件后,SpringFactoriesLoader将查询配置文件命名的属性。
这样@EnableAutoConfiguration自动配置的过程就是:从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure.EnableutoConfiguration对应的配置项通过反射(Java Refletion)实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。
SpringApplication.run
SpringApplication的run方法的主要流程大体可以归纳如下:
1、创建和配置环境
根据初始化的配置创建environment的类型,包括配置要使用的PropertySource以及Profile。
启动监听器的environmentPrepared方法,调用所有监听器来监听。
如果SpringApplication的showBanner属性被设置为true,则打印banner。
2、创建ApplicationContext
根据用户是否明确设置了applicationContextClass类型以及初始化阶段的推断结果,决定该为当前SpringBoot应用创建什么类型的ApplicationContext并创建完成,然后根据条件决定是否添加ShutdownHook,决定是否使用自定义的BeanNameGenerator,决定是否使用自定义的ResourceLoader,当然,最重要的,将之前准备好的Environment设置给创建好的ApplicationContext使用。
3、加载资源,就是在初始化过程中source包含的类
4、context 重新刷新
调用ApplicationContext的refresh()方法,完成IoC容器可用的最后一道工序。
5、配置spring boot特有的单例bean 如commandline相关
6、监听器实现所有finished操作
遍历执行SpringApplicationRunListener的finished()方法。
至此,Spring boot的启动过程就完成了。