Spring Boot之常见问题解惑

FailureAnalyzer

FailureAnalyzer 用于拦截我们感兴趣的异常,并将其包装到更具可读性的 FailureAnalysis ,比如application-context相关的异常,默认的实现AbstractFailureAnalyzer 继承于 FailureAnalyzer ,用于检查是否出现了特定的异常。如果需要访问到BeanFactoryEnvironment,可以实现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);
		}
	}

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章