安装 spring CLI(command line interface),后再运行本地 groovy 文件。
.1. spring boot 的简化处理
- 将所有依赖都写入其基本配置中,最大简化其配置;
- 自动扫描,一个注解自动识别所有的需要扫描的包与 bean;
@RestController
指定此类为一个特殊处理器, spring 会识到并用来处理网络请求;@RequestMapping
提供 “路由” 信息给 spring ,spring 也会对处理结果进行渲染返回给调用者;@EnableAutoConfiguration
有这个注解 spring boot 会主动根据 pom 文件引入的依赖为你配置,eg: pom 中配置了spring-boot-starter-web
, spring boot 会假设工程是一个 web 应用并为其添加相应的依赖。@ComponentScan
自动扫描包中的 spring 组件。@Configuration
相当于 spring bean 的容器,也可以外部的 bean 或配置组件导入。@SpringBootApplication
声明 spring boot 入口,拥有的功能相当于@EnableAutoConfiguration
@Configuration
@ComponentScan
三者之和。同时, spring boot 的入口类最好放在包根路径下,因为组件扫描时时会隐式地将此注解所在类定义为 search package 。@SpringBootApplication
和@EnableAutoConfiguration
永远只添加一个,一般建议选择任意一个添加到主@Configuration
类上。- 组件导入
- 建议使用
@Configuration
java 组件,@Import
可用来将其他组件导入,也可以使用@ComponentScan
自动扫描所有的 spring 组件,包括@Configuration
配置组件 - 如果非要使用 xml 配置,使用
@ImportResource
- 建议使用
.1.1. create an executable jar
对于一个工程来说依赖各个 jar 包,而 java 并没有提供一个标准的方式去加载内嵌的 jar ,因此不能发布一个独立的程序包。
为此,很多开发者的解决方案是创建一个 ‘uber’ jar,所谓 uber jar 是指将应用所有的依赖的 class 文件整合成一个单独的包。这样做的问题在于:1、 难以查看依赖库;2、不同 jar 包中要是存在同名的 class 就会出现问题。
spring boot 使用了不同的方式达到直接使用内嵌包。
- 打包:
mvn package
- 查看 jar 包内打包文件
mvn tvf jar_file
- pom 中 groupid
org.springframework.boot
- 指定打包为可执行 jar 包的插件
1 | <build> |
.2. how to series
.2.1. spring 项目中使用 profile
用以指定当前运行环境,可以 maven 打包时也可以设置针对环境打包。
获取当前活跃的 profile ,参考 6. Get Active Profiles
.3. Structuring Code
.3.1. Locating the Main Application Class
- 在根目录添加 Application.class 主类放在根目录上,使用
@SpringBootApplication
注解在主类上。此注解也隐匿地定义了某些特定项目的基础查找包base search package
。_如果在root package 定义多个 application.class 打包发布时会认定哪个为项目入口呢?_亲测结果:spring-boot-maven-plugin:2.3.1.RELEASE:repackage failed: Unable to find a single main class from the following candidates
打包插件将报出不能找到唯一的主类异常 - 若不使用
@SpringBootApplication
注解,可以使用@EnableAutoConfiguration
@ComponentScan
两个注解实现相同功能
.3.2. Auto-configuration
自动配置
- 使用
@EnableAutoConfiguration
后,spring boot 会检测 classpath 所有的内容进行自动添加配置。 - 可以在运行时加上 –debug 进入 debug 模式查看自动配置了哪些东西。
- 应该逐渐用特定的配置代替自动配置。
- 若 spring boot 自动配置了不需要的配置,可以在
@SpringBootApplication
或@EnableAutoConfiguration
添加排除 exclude ,若排除的类不在 classpath 中可以指定其全限定名到excludename
。也可以添加配置spring.autoconfigure.exclude
指定自动配置排除配置。
.3.3. Spring Beans and Dependency Injection
- spring 中的 bean 注入:使用构造器注入
private final Dependency d;
使用 final 修辞字段让其不能被修改。
.3.4. Using the @SpringBootApplication Annotation
@SpringBootApplication 注解有三个特性,分别对应三个注解:
- @EnableAutoConfiguration
- @ComponentScan
- @Configuration
@SpringBootApplication 提供别名以实现定义以上前两个注解的功能。
.4. Developer Tools
添加 spring-boot-devtools 依赖,实现热启动。其实现原理是固有的jar包代码使用一个固定的 classloader,而开发变动的代码使用另一个classloader,当发生变动时,重启一个 classloader 加载新的编译的代码。所以热启动相对冷启动要快些,因为其不用加载旧的不变的依赖的jar包中的代码。
- 使用 trigger-file 触发项目重启。
spring.devtools.restart.trigger-file=<.reloadtrigger>
手动更新了 trigger 文件才会触发更新。trigger 文件可以自定义在 classpath 中任意地方,而配置文件指定配置文件不需要全限定名,更新代码后只需要修改保存一下trigger文件即可触发reload。 - 如果使用了Ultimate Edition IDEA 可以点击 relauch 触发重启。
- 生产模式下devtool 自动关闭,如果项目启动通过 java -jar 运行一个包或从一个特定的 classloader 中开始,devtools 将自动识别在生产模式中。如果应用在窗口中开启需要排除 devtools 或者直接添加系统参数
-Dspring.devtools.restart.enabled=false
。
.5. Source Code
Spring Boot 源码
.5.1. 单例 bean 注册器中 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
- dependentBeanMap 注释
Map between dependent bean names: bean name to Set of dependent bean names.
表示 bean 与依赖此 bean 的映射 map 。 - dependenciesForBeanMap
Map between depending bean names: bean name to Set of bean names for the bean's dependencies.
表示 bean 与 此 bean 依赖的 bean 的映射关系集合。- 上述结论来自方法 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#registerDependentBean 及其注释说明。同时可以从自动装配方法 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireByType line:1511 推导:解析本bean 自动装配的依赖 autowiredBeanNames 出后,在注册处调用方法 line:1516 参数是本 bean 依赖 autowiredBeanName 为第一个参数,而本 beanName 是第二个参数(这时的依赖关系是: 本bean 依赖 autowiredBean)。再看此 registerDependentBean 方法,其执行是将第一个参数 beanName(此时就是本 bean 的依赖bean) 放入了 dependenciesForBeanMap 而 本 beanName 作为 了第二个参数 放入了 dependentBeanMap 。
- CGLIB 策略生成子类创建 bean: org.springframework.beans.factory.support.CglibSubclassingInstantiationStrategy.CglibSubclassCreator#createEnhancedSubclass