目录
关于@SpringBootApplication这个注解的作用,记住下面这张图即可:
自动配置幕后英雄:SpringFactoriesLoader详解
Spring Boot是什么?
Spring Boot是为简化Spring MVC/spring的开发而生的项目。主要从以下三个方面:
-
simplify configuration 简化配置
-
simplify deployment简化部署
-
simplify monitor 简化系统监控
spring boot由四个主要的组件组成:
-
Spring Boot Starter:
-
Automatically Configuration.
-
CLI. Use with groovy.
-
Actuator
Spring Boot Starter
spring boot starter起到的作用是,把一些列的依赖结合起来,依赖之间可以像java类继承一样引用对方。这样的好处是解决了依赖之间冲突的问题(这个问题在maven使用过程中非常常见),减少了依赖的数量。
下面是一个spring boot starter web的例子:
在这个时代,使用spring开发的应用大多数都是在使用springMVC开发web应用,为了帮我们快速搭建并开发一个web项目,spring boot为我们提供了spring-boot-starter-web自动配置模块。
只要将spring-boot-starter-web加入项目的maven依赖,我们就得到了一个直接可执行的web应用,在当前项目下运行spring boot:run,就可以直接启动一个使用了嵌入式Tomcat服务的web应用,只不过我们还没有提供任何可以响应web请求的controller,所以当前访问任何的路径都会返回一个spring boot默认提供的错误页面(white label error page). 如果在当前项目下新建一个服务根路径web请求的controller:
@RestController
public class IndexController {
@RequestMapping("/")
public String index(){
return "hello, there";
}
}
重新运行mvn spring-boot:run并访问http://localhost:8080,错误页面将被controller返回的消息所替代。至此,一个简单的web应用就已经这样完成了。但是,毫无疑问背后的潜规则(约定)是我们必须去了解的。
约定1:项目结构层面的约定
与传统打包为war包的java web应用的差异在于,静态文件和页面模板的存放位置变了,原来是放在src/main/webapp目录下的一系列资源,现在都统一放在了src/main/resources下。
约定2:springMVC框架层面的约定和定制
spring-boot-starter-web默认为我们配置了一些springMVC必要组件
- ViewResolver
- Converter,Formatter等bean注册到IoC
- HttpMessageConverter
- MessageCodesResolver
当然,我们完全可以自己配置这些东西,而不用它提供的配置。
约定3:嵌入式web容器层面的约定和定制
- 默认使用嵌入式tomcat作为web容器对外提供http服务,默认使用8080端口对外监听和提供服务
- 假设不行使用签署tomcat,可引入spring-boot-starter-jetty或spring-boot-starter-undertow作為替代
- 假设不想使用8080作为默认端口,可以更改配置项server.port使用自己指定的端口号,如:server.port = 9000
Automatically Configuration
自动配置的主要职责是:减少spring的配置。
自动配置是什么,用一个例子比较好说明。当我们把spring-boot-starter-web加入到项目的maven依赖里以后,它就会自动的添加spring mvc的相关依赖,如果spring mvc相关的配置在classpath里面被scan到,它就会自动的将相关的bean加到IoC容器里面(messageConvert等)。spring启动的时候会扫描classpath并且去找META-INF/spring.factories这个文件,然后去加载configuration. 这个文件的格式是 key = value的格式,并且key和value都必须是java 类的全限定名(Fully qualified), 比如:
exmaple.MyService = example.MyServiceImpl
如果我们使用了注解@EnableAutoConfiguration,它会去加载,实例化所有加了@Configuration的注解的类到IoC容器里去(ApplicationContext),通常,这个注解会用在主类里边,并且主类一般是在开发包的最顶部,因此它就可以扫描到所有的类。
@EnableAutoConfiguration这个注解的示意图如下:
@ComponentScan:
会自动扫描包路径下面的所有@Controller、@Service、@Repository、@Component 的类。
basePackages指定扫描的包,includeFilters包含那些过滤,excludeFilters不包含那些过滤,useDefaultFilters默认的过滤规则是开启的,如果我们要自定义的话是要关闭的
@Configuration
把一个类标记为IoC容器的一个bean
关于@SpringBootApplication这个注解
这个注解由下面几个注解组成:
@Configuration
它就是JavaConfig形式的Spring Ioc容器的配置类使用的那个@Configuration.
这里的启动类标注了@Configuration之后,本身其实也是一个IoC容器的配置类。
任何一个标注了@Configuration的Java类定义都是一个JavaConfig配置类。
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
这个springBoot启动类等价于下面的写法:
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class AppConfiguration{
@Bean
public Controller controller(){
return new Controller();
}
}
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(AppConfiguration.class, args);
}
}
经过这样的改造之后,就很明白了,启动类就是一个普通的main函数启动类,没有什么特别之处,在main 里面调用了一个方法而已。
而由@Configuration修饰的AppConfiguration类定义就是一个普通的javaConfig形式的IoC容器配置类而已。
@ComponentScan
@ComponentScan这个注解在Spring中很重要,它对应XML配置中的元素,@ComponentScan的功能其实就是自动扫描并加载符合条件的组件(比如@Component和@Repository等)或者bean定义,最终将这些bean定义加载到IoC容器中。
我们可以通过basePackages等属性来细粒度的定制@ComponentScan自动扫描的范围,如果不指定,则默认Spring框架实现会从声明@ComponentScan所在类的package进行扫描。
p.s. 所以SpringBoot的启动类最好是放在root package下,因为默认不指定basePackages
@EnableAutoConfiguration
@EnableAutoConfiguration是借助@Import的帮助,将所有符合自动配置条件的bean定义加载到IoC容器,仅此而已。
它本事也是一个复合的注解,它的实现如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
...
}
最关键的要属@Import(EnableAutoConfigurationImportSelector.class),借助EnableAutoConfigurationImportSelector,@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器.
借助于Spring框架原有的一个工具类:SpringFactoriesLoader的支持,@EnableAutoConfiguration可以智能的自动配置功效才得以大功告成.
自动配置幕后英雄:SpringFactoriesLoader详解
SpringFactoriesLoader属于Spring框架私有的一种扩展方案,其主要功能就是从指定的配置文件META-INF/spring.factories加载配置。
配合@EnableAutoConfiguration使用的话,它更多是提供一种配置查找的功能支持,即根据@EnableAutoConfiguration的完整类名org.springframework.boot.autoconfigure.EnableAutoConfiguration作为查找的Key,获取对应的一组@Configuration类.
以下是从springBoot的:spring-boot-autoconfigure依赖包中的截图:
@EnableAutoConfiguration自动配置的魔法就是:从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure.EnableautoConfiguration对应的配置项通过反射(Java Refletion)实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。
在我们启动spring boot的app时会调用一个SpringBootApplication的run方法。这个方法在执行过程中会去主动初始化需要用到的bean。其重要实现如下:
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
if (result != null) {
return result;
} else {
try {
Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
LinkedMultiValueMap result = new LinkedMultiValueMap();
while(urls.hasMoreElements()) {
URL url = (URL)urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
Iterator var6 = properties.entrySet().iterator();
while(var6.hasNext()) {
Entry<?, ?> entry = (Entry)var6.next();
List<String> factoryClassNames = Arrays.asList(StringUtils.commaDelimitedListToStringArray((String)entry.getValue()));
result.addAll((String)entry.getKey(), factoryClassNames);
}
}
cache.put(classLoader, result);
return result;
} catch (IOException var9) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var9);
}
}
}
可以看到,是从一个名字(变量FACTORIES_RESOURCE_LOCATION)叫spring.factories的资源文件中,读取所有的配置信息存放在了一个LinkedMultiValueMap类型的局部变量result当中。
Acutator
spring提供了actutator用于帮助我们监控服务的各种状态:
路径 | 作用 |
info |
know the service situation |
error | |
autoconfig | list config decisions |
beans | List all the config beans |
dump | List application’s thread information |
/env/{name} | list all the environment variables |
health | |
info | |
/metrics/{name} | list the realated index |
shutdown | shut down the service |
trace | list the recent quest metadata,include request and response header |
configprops | list all the @ConfigurationProperties |
spring boot启动过程
spring boot项目的启动过程大致如下图: