今天遇到一个情况,比如:
2021-01-07 11:43:01,367 WARN (Configuration.java:283) - For more details, go to https://vladmihalcea.com/hypersistence-optimizer/
2021-01-07 11:43:01,368 INFO (Configuration.java:285) -
_ _ _ _
| | | | (_) | |
| |__| |_ _ _ __ ___ _ __ ___ _ ___| |_ ___ _ __ ___ ___
| __ | | | | '_ \ / _ \ '__/ __| / __| __/ _ \ '_ \ / __/ _ \
| | | | |_| | |_) | __/ | \__ \ \__ \ || __/ | | | (_| __/
|_| |_|\__, | .__/ \___|_| |___/_|___/\__\___|_| |_|\___\___|
__/ | |
|___/|_|
____ _ _ _
/ __ \ | | (_) (_)
| | | |_ __ | |_ _ _ __ ___ _ _______ _ __
| | | | '_ \| __| | '_ ` _ \| |_ / _ \ '__|
| |__| | |_) | |_| | | | | | | |/ / __/ |
\____/| .__/ \__|_|_| |_| |_|_/___\___|_|
| |
|_|
应用启动的时候,打印了这样的banner。这个在本地开发环境我也就忍了,但是上了生产和测试的时候,使用EFK管理日志的话,这个banner存储在EFK上简直就不能看!
所以,我准备把他关掉。
在网上看了下作者vladmihalcea
给的解决方案:https://github.com/vladmihalcea/hibernate-types/issues/196 。需要通过配置项hibernate.types.print.banner
关闭。
可实际测试发现,这种关闭方法,需要写系统环境变量才能生效。可是,作为一个Spring Boot的框架,难道不应该要支持通过配置文件application.properties
配置所有可配置信息吗?
源代码奉上:
private void printBanner() {
String printBannerValue = properties.getProperty(PropertyKey.PRINT_BANNER.getKey());
if(printBannerValue != null && !Boolean.valueOf(printBannerValue)) {
return;
}
LOGGER.warn("You should use Hypersistence Optimizer to speed up your Hibernate application!");
LOGGER.warn("For more details, go to https://vladmihalcea.com/hypersistence-optimizer/");
LOGGER.info(
StringUtils.join(
StringUtils.LINE_SEPARATOR,
"",
" _ _ _ _",
"| | | | (_) | |",
"| |__| |_ _ _ __ ___ _ __ ___ _ ___| |_ ___ _ __ ___ ___",
"| __ | | | | '_ \\ / _ \\ '__/ __| / __| __/ _ \\ '_ \\ / __/ _ \\",
"| | | | |_| | |_) | __/ | \\__ \\ \\__ \\ || __/ | | | (_| __/",
"|_| |_|\\__, | .__/ \\___|_| |___/_|___/\\__\\___|_| |_|\\___\\___|",
" __/ | |",
" |___/|_|",
"",
" ____ _ _ _",
" / __ \\ | | (_) (_)",
" | | | |_ __ | |_ _ _ __ ___ _ _______ _ __",
" | | | | '_ \\| __| | '_ ` _ \\| |_ / _ \\ '__|",
" | |__| | |_) | |_| | | | | | | |/ / __/ |",
" \\____/| .__/ \\__|_|_| |_| |_|_/___\\___|_|",
" | |",
" |_|",
""
)
);
LOGGER.info("Check out the README page for more info about the Hypersistence Optimizer banner https://github.com/vladmihalcea/hibernate-types#how-to-remove-the-hypersistence-optimizer-banner-from-the-log");
}
那遇到这种情况,该怎么办呢?
可以通过Spring Boot中提供的EnvironmentPostProcessor
方法,基于Spring Boot自动装配的功能实现上面的功能。下面给出解决方案:
-
在
/src/main/resources
目录下创建/META-INF/spring.factories
文件 -
在文件中增加一行配置:
org.springframework.boot.env.EnvironmentPostProcessor=\
com.xxx.xxx.property.SystemPropertyInjectEnvironmentPostProcessor
-
在工程中编写如下业务代码:
import com.google.common.base.Strings;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.env.ConfigurableEnvironment;
/**
* @author jingxuan
* @date 2021/1/7 11:38 上午
*/
public class SystemPropertyInjectEnvironmentPostProcessor implements EnvironmentPostProcessor {
protected static final String HIBERNATE_TYPE_BANNER_PROPERTY_FILE_KEY = "spring.jpa.properties.hibernate.types.print.banner";
// 不考虑使用PropertyKey.PRINT_BANNER.getKey(),因为不想强依赖这个包
protected static final String HIBERNATE_TYPE_BANNER_SYSTEM_PROPERTY_KEY = "hibernate.types.print.banner";
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
// 从配置文件中读取cat.name的属性值,并写入到app.name的环境变量中(CAT需要用到)
this.setSystemProperty(environment, HIBERNATE_TYPE_BANNER_PROPERTY_FILE_KEY, HIBERNATE_TYPE_BANNER_SYSTEM_PROPERTY_KEY);
}
private void setSystemProperty(ConfigurableEnvironment environment, String propertyFileKey, String systemPropertyKey) {
if (System.getProperty(systemPropertyKey) != null) {
return ;
}
String propertyValue = environment.getProperty(propertyFileKey);
if (!Strings.isNullOrEmpty(propertyValue)) {
System.setProperty(systemPropertyKey, propertyValue);
}
}
}
-
在配置文件中,增加如下配置项:
spring:
jpa.properties.hibernate:
# 这个属性不是作用在JpaProperties中的,是作用在com.vladmihalcea.hibernate.type.util.Configuration上的,放在这只不过是因为逻辑上属于一个模块
types.print.banner: false
再次启动应用,banner就消失不见啦。
这样能生效的原理是:Spring Boot生命周期中,会先实例化Environment
,再开始进入bean对象的实例化操作。在Environment
完成实例化之后,Spring Boot框架会调用所有注册的EnvironmentPostProcessor
类,这样用户就可以根据实际需要再bean实例化之前,执行一部分业务逻辑了。