1、分析启动失败
若spring boot 启动失败时,会将异常信息打印到控制台上,我们通常的做法是查看日志,然后去谷歌,百度搜索异常的解决方案。这取决于我们的经验和知识,对异常越熟悉,解决问题的速度也越快,例如遇到NullPointException甚至无需搜索便可快速解决。
在启动spring boot时,它也会抛出许多异常,若是非常精通spring boot,分析异常,分析启动失败的原因不会很难。但是绝大多数情况下我们不了解spring boot的内部机制,结构,甚至某些异常抛出后,甚至不知道异常的含义。
Spring boot提供了一种机制,注册FailureAnalyzers可以帮助我们分析异常。这种做法类似于语文老师将文言文翻译成白话文。原始异常类似于文言文,它晦涩难懂,FailureAnalyzer类似于老师的白话文,当异常抛出之后,打印在控制台上的不是原始异常的信息,而是经过分析之后的异常信息。
实现FailureAnalyzer的步骤如下:
- 第一步,需要实现FailureAnalyzer接口。它只有一个方法analyze,方法的参数类型为Throwable。
- 第二步,注册FailureAnalyzer,具体的做法是把接口的实现类添加到spring-boot-version.jar包,META-INF目录下的spring.factories文件。打开文件还可以看到许多内置的FailureAnalyzer。
2、延迟加载
当全局性的设置延迟加载时,有两种方式
- 设置spring.main.lazy-initialization属性值为true。
- 调用builder.setLazyInitialization方法。
当个别设置延迟加载时,在类上添加@Lazy注解,如果是@Bean注入的bean,设置注解的lazy-init属性。
3、Banner
Banner是指横幅的意思,它的配置有两个层面,第一个层面是横幅的Mode,第二个层面是横幅的内容。它们都有两种方式,配置文件和API方式
3.1 Mode
Mode是一个枚举类,它有三个值,含义如下:
- Console:打印到输出台上
- LOG:打印到日志文件中
- OFF:关闭
设置它的方式,配置文件方式
# 或者是console,log spring.main.banner-mode=off
API方式,可以是OFF,CONSOLE
builder.bannerMode(Banner.Mode.OFF);
3.2 横幅的内容
设置横幅的内容本质是设置Banner的实现类,Spring框架默认有三种
- SpringBootBanner:默认的方式,输出Spring boot横幅
- ResourceBanner:由资源文件提供Banner的内容
- ImageBanner:Banner的内容为图片。
也可以自定义实现Banner接口,例如
/** * * @Title: MessageBanner.java * @Package learn.spring.boot.banner * @Description: 自定义Banner,输出一条message * @version V1.0 */ public class MessageBanner implements Banner { // 自定义消息 private String message; public MessageBanner(String message) { this.message = message; } @Override public void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) { out.print(this.message); } }
该示例中MessageBanner输出一条Message作为Banner的内容。
API的方式,其中banner方法的参数为Banner接口实现类对象
builder.banner(new MessageBanner(" This IS MY OWN TEST BANNER! "));
如果想要自定义更炫酷的Banner内容,可以访问如下网站:http://patorjk.com/software/taag/,http://www.network-science.de/ascii/
4、创建IOC
创建IOC容器,体现在代码是创建ApplicationContext对象,它有三种形式,
- 注解方式,此时创建AnnotationConfigApplicationContext对象,构造器参数是1到多个配置类(类上有@Configuration),或1到多个Bean(类上有@Component或@Service等)
- 配置文件,创建XML配置文件,以前的主流方式。
- 混合方式,在配置类上添加@ImportReSource引入配置文件。
5、Builder API
可以参考SpringApplicationBuilder的API。大部分的方法没有必要去逐个研究,这些方法只是提供了另外一种配置方式。例如在设置banner时,设置相关配置项,与调用builder的API都可以达到目的。
6、事件与监听器
引用原著中的内容:
1. An ApplicationStartingEvent is sent at the start of a run but before any processing, except for the registration of listeners and initializers.
ApplicationStartingEvent在项目启动,注册监听器和初始化器之后。在处理任何请求之前
2. An ApplicationEnvironmentPreparedEvent is sent when the Environment to be used in the context is known but before the context is created.
ApplicationEnvironmentPreparedEvent在容器获取Envionment之后,在ApplicationContext对象创建之前。
3. An ApplicationContextInitializedEvent is sent when the ApplicationContext is prepared and ApplicationContextInitializers have been called but before any bean definitions are loaded.
ApplicationContextInitializedEvent在ApplicationContext对象创建之后,在加载BeanDefinition类之前。
4. An ApplicationPreparedEvent is sent just before the refresh is started but after bean definitions have been loaded.
ApplicationPreparedEvent在加载BeanDefiniition之后,在context刷新之前,当项目路径中存在修改时,会导致刷新。也可以直接调用context.refresh方法刷新。
5. An ApplicationStartedEvent is sent after the context has been refreshed but before any application and command-line runners have been called.
ApplicationStartedEvent在context刷新之后,在运行CommandLineRunner接口之前。
6. An ApplicationReadyEvent is sent after any application and command-line runners have been called. It indicates that the application is ready to service request
ApplicationReadyEvent在CommandLinerRunner接口运行之后触发。
7. An ApplicationFailedEvent is sent if there is an exception on startup
ApplicationFailedEvent在项目启动失败后触发。
在ApplicationPreparedEvent和ApplicationStartedEvent之间还存在ContextRefreshedEvent,WebServerInitializedEvent。
1. A ContextRefreshedEvent is sent when an ApplicationContext is refreshed.
Context每次刷新都会触发ContextRefreshedEvent
2. A WebServerInitializedEvent is sent after the WebServer is ready. ServletWebServerInitializedEvent and ReactiveWebServerInitializedEvent are the servlet and reactive variants respectively
当内置的Web Server启动之后,会触发WebServerInitializedEvent。
7、WEB
当spring boot 检测到web项目时(添加starter-web依赖),会创建XXXWebServerApplicationContext。
当spring boot 未检测到web项目,但检测到webFlux,会创建XXXReactiveWebServerApplicationContext。
当spring boot 都未检测到时,会创建XXXApplicationContext。
当只想运行Junit测试时,可以手动调用builder的setWebApplicationType(WebApplicationType.NONE)。
8、Application Arguments
这里的参数是指Program arguments。获取这些参数的方式有三种:
- 直接获取main方法中的args参数,它是一个数组
- 实现ApplicationRunner接口,它将参数封装为AplicationArguments对象,并且将参数分为两类,一种是Option,它是通过--key=value的形式来指定的,另外一种是NonOption,它是通过“-”来指定的。可以看出它们的数据结构是不同的,一种是键值对,另外一种是字符串数组。
- 实现CommandLineRunner接口,它与直接遍历args参数是一样的,它的数据结构只有字符串数组。
8.1 ApplicationRunner
@Override public void run(ApplicationArguments args) throws Exception { // -方式指定的参数,数据格式为字符串数组 List<String> arguments = args.getNonOptionArgs(); System.out.println("**********************************"); for (String current : arguments) { System.out.println(current); } // --方式指定的参数,数据格式为键值对 Set<String> optionNames = args.getOptionNames(); System.out.println("**********************************"); for (String current : optionNames) { System.out.println(current + " : " + args.getOptionValues(current)); } }
8.2 CommandLineRunner
@Override public void run(String... args) throws Exception { System.out.println("*******************"); for (String current : args) { System.out.println(current); } }
9、Application Exit
普通的Java程序,调用System.exit(0)表示正常结束,System.exit(1)表示异常结束,这里的参数可以是任何非0的整数。
类似的,SpringApplication也有exit方法,若当前IOC容器中存在类型为ExitCodeGenerator的Bean,它会实现getExitCode方法,该方法的返回值为SpringApplication.exit的返回值。
它的作用是可以自定义异常码,分析spring boot项目异常退出的原因。
10、Admin
设置spring.application.admin.enabled为true时,可以通过JMX监控SpringApplicationAdminMXBean。