FailureAnalyzer
FailureAnalyzer 用于拦截我们感兴趣的异常,并将其包装到更具可读性的 FailureAnalysis ,比如application-context相关的异常,默认的实现AbstractFailureAnalyzer 继承于 FailureAnalyzer ,用于检查是否出现了特定的异常。如果需要访问到BeanFactory或Environment,可以实现BeanFactoryAware orEnvironmentAware接口。对于处理不了的异常,我们直接返回 null 以便其他分析器可以处理。FailureAnalyzer 应该配置在 META-INF/spring.factories.才能生效,如:ProjectConstraintViolationFailureAnalyzer。
org.springframework.boot.diagnostics.FailureAnalyzer=\
com.example.ProjectConstraintViolationFailureAnalyzer
Auto-configuration
Spring Boot自动配置提供了很多默认设置,方便我们快速建立一个spring boot应用,但是也常常让我们感觉对具体的配置失去了控制,往往有问题也不知道从哪查起。调试的我们可以利用 ConditionEvaluationReport 来输出具体的配置信息。如果添加了 spring-boot-actuator 模块,可以在 conditions 端点看到JSON格式的配置信息。更多的时候可能需要我们自己去看源码:
首先可以看 *AutoConfiguration 结尾的自动配置类,里面一般有很多 @Conditional* 开头的约束注解。这些表明在什么时候启用哪些配置,可以通过 --debug 或系统参数 -Ddebug 打开查看自动配置的日志,在Actuator模块的 conditions 端点也可以看到相关信息 (/actuator/conditions )。
查看 @ConfigurationProperties 注解(比如 ServerProperties),通过这里读取外部配置项,这个注解有一个 name 属性表明了配置项的前缀。比如 ServerProperties(name="server") 则读取 server.port, server.address等,在Actuator 的 configprops 端点也可以看到。
查看Binder类的 bind 方法,用于显示的绑定 Environment 参数,以及 @Value @ConditionalOnExpression 等注解。
Customize
SpringApplication可以添加多个 ApplicationListeners和ApplicationContextInitializers来实现在启动前对context或environment的自定义。比如Spring Boot就通过 META-INF/spring.factories加载很多配置项。我们也可以添加自己的配置项:
可以直接在代码中调用SpringApplication 的addListeners和addInitializers方法来添加;
也可以通过配置文件application.properties里面的 context.initializer.classes 和
context.listener.classes properties项;
如果是针对所有应用生效则可以添加 META-INF/spring.factories,并打成jar包来引用。
SpringApplication会发送一些特定的 ApplicationEvents到listeners (有些是在context被创建之前的),然后将这些listeners注册到 ApplicationContext。
同时还可以通过实现EnvironmentPostProcessor接口,在Environment刷新之前添加配置,同样实现类也需要配到META-INF/spring.factories,如
org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostProcessor
如下实现了从classpath 加载 YAML 文件到 Environment:
package hello;
import java.io.IOException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
public class EnvironmentPostProcessorExample implements EnvironmentPostProcessor {
private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) {
Resource path = new ClassPathResource("com/example/myapp/config.yml");
PropertySource<?> propertySource = loadYaml(path);
environment.getPropertySources().addLast(propertySource);
}
private PropertySource<?> loadYaml(Resource path) {
if (!path.exists()) {
throw new IllegalArgumentException("Resource " + path + " does not exist");
}
try {
return this.loader.load("custom-resource", path, null);
}
catch (IOException ex) {
throw new IllegalStateException(
"Failed to load yaml configuration from " + path, ex);
}
}
}