中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何解決spring-boot使用logback的問題

發布時間:2021-07-27 13:43:26 來源:億速云 閱讀:97 作者:小新 欄目:開發技術

這篇文章主要介紹了如何解決spring-boot使用logback的問題,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

用ConsoleAppender.java來舉例,假設在logback.xml中使用了該appender,那么這個類的相關的初始化方法都會調兩次,如start()方法

打斷點進行debug,第一次進入start()方法如下:

如何解決spring-boot使用logback的問題

可以看到所有的調用鏈(除了自己代碼的方法)都是logback或者slf4j相關的比較正常

當跳過該斷點時又會進入以此這個方法,看下調用鏈:

如何解決spring-boot使用logback的問題

可以看到這次的初始化是由spring-boot發起的,所以這樣logback初始化一次,然后spring-boot初始化一次,一共兩次

我們現在可以將spring-boot的初始化去掉

debug代碼可以發現LoggingApplicationListener.java這個監聽器主要是用來初始化spring-boot的日志系統,現在目的將該listener在啟動之前去掉

spring-boot的啟動代碼為:

new SpringApplicationBuilder(Launcher.class).application().run(args);

在SpringApplicationBuilder.java的構造方法打斷點進行跟蹤,

進入SpringAppication.java會發現該類中的代碼:

private void initialize(Object[] sources) {
   if (sources != null && sources.length > 0) {
      this.sources.addAll(Arrays.asList(sources));
   }
   this.webEnvironment = deduceWebEnvironment();
   setInitializers((Collection) getSpringFactoriesInstances(
         ApplicationContextInitializer.class));
   setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
   this.mainApplicationClass = deduceMainApplicationClass();
}

第八行應該就是注冊監聽器的地方了,繼續往下跟蹤,進入以下方法:

private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,
      Class<?>[] parameterTypes, Object... args) {
   ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
   // Use names and ensure unique to protect against duplicates
   Set<String> names = new LinkedHashSet<String>(
         SpringFactoriesLoader.loadFactoryNames(type, classLoader));
   List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
         classLoader, args, names);
   AnnotationAwareOrderComparator.sort(instances);
   return instances;
}

繼續進入loadFactoryNames()方法,核心就在這里了

public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
   String factoryClassName = factoryClass.getName();
   try {
      Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
            ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
      List<String> result = new ArrayList<String>();
      while (urls.hasMoreElements()) {
         URL url = urls.nextElement();
         Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
         String factoryClassNames = properties.getProperty(factoryClassName);
         result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
      }
      return result;
   }
   catch (IOException ex) {
      throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
            "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
   }
}

FACTORIES_RESOURCE_LOCATION這個常量的值為META-INF/spring.factories,

打開該文件可以發現:

# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.context.web.ServerPortInfoApplicationContextInitializer
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener,\
org.springframework.boot.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.logging.LoggingApplicationListener
# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor
# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer
# FailureAnalysisReporters
org.springframework.boot.diagnostics.FailureAnalysisReporter=\
org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter

ApplicationListener應該就是我們需要修改的地方了,去掉org.springframework.boot.logging.LoggingApplicationListener就可以了,我們可以在代碼里面覆蓋一份這塊代碼從而實現去掉這行,但是實際得再跑一遍,發現還是一樣初始化兩次

問題出在

Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
      ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));

這塊代碼是將所有的META-INF/spring.factories都讀取過來了然后進行合并,所以說哦這個META-INF/spring.factories只能增加內容,但是不能去掉某些內容,沒辦法了只能在代碼初始化了所有的listener之后再將listener去掉,

具體代碼如下(啟動spring-boot的main方法中):

SpringApplicationBuilder builder = new SpringApplicationBuilder(Launcher.class);
Set<ApplicationListener<?>> listeners = builder.application().getListeners();
for (Iterator<ApplicationListener<?>> it = listeners.iterator(); it.hasNext();) {
    ApplicationListener<?> listener = it.next();
    if (listener instanceof LoggingApplicationListener) {
        it.remove();
    }
}
builder.application().setListeners(listeners);
builder.run(args);

感謝你能夠認真閱讀完這篇文章,希望小編分享的“如何解決spring-boot使用logback的問題”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

塔城市| 耿马| 定陶县| 山东| 西安市| 开封县| 河北省| 曲麻莱县| 新建县| 西贡区| 西华县| 容城县| 喜德县| 静海县| 汝南县| 陆河县| 沿河| 临城县| 郎溪县| 江永县| 云浮市| 祁东县| 三门县| 牙克石市| 建平县| 门源| 伊宁县| 洛南县| 江达县| 安丘市| 大邑县| 望江县| 乐亭县| 桑植县| 曲沃县| 武隆县| 常熟市| 德昌县| 东乌珠穆沁旗| 南投县| 衢州市|