What's wrong with my attempt to change Spring&

2019-02-28 11:22发布

问题:

I'm a neophyte to Spring Boot, and I wanted to change my default logger to log4j2, since it has a higher throughput rate than logback.

Here's my Gradle script. As you can see, I am using Spring Boot 2.0.3, and to disable the default logger I used exclude module(logback and spring boot starter logger) after Spring Boot Web. I am compiling log4j at the bottom of my script.

buildscript {
    ext {
        springBootVersion = '2.0.3.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}



apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

group = 'app'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8



repositories {
    mavenCentral()
    jcenter()
}


ext {
    vaadinVersion = '8.4.1'
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-data-rest')
    providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
    compile('org.springframework.boot:spring-boot-starter-security')
    compile('org.springframework.boot:spring-boot-starter-thymeleaf')
    compile('org.springframework.boot:spring-boot-starter-web') {
        exclude module: "spring-boot-starter-logging"
        exclude module: "logback-classic"
    }
    compile('org.springframework.boot:spring-boot-starter-webflux')
    compile('org.springframework.boot:spring-boot-starter-jdbc')
    compile('org.springframework.boot:spring-boot-starter-log4j2')
    compile('com.vaadin:vaadin-spring-boot-starter')
    runtime('org.springframework.boot:spring-boot-devtools')
    compileOnly('org.springframework.boot:spring-boot-configuration-processor')
    compileOnly('org.projectlombok:lombok')
    testCompile('org.springframework.boot:spring-boot-starter-test')
    testCompile('io.projectreactor:reactor-test')
    testCompile('org.springframework.security:spring-security-test')
    testCompile 'junit:junit:4.12'


    compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.1'
    compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.1'
    // https://mvnrepository.com/artifact/com.h2database/h2
    //compile group: 'com.h2database', name: 'h2', version: '1.0.60'
    testCompile group: 'com.h2database', name: 'h2', version: '1.3.148'





}

dependencyManagement {
    imports {
        mavenBom "com.vaadin:vaadin-bom:${vaadinVersion}"
    }
}

This is my Spring Boot application.

package app.clothapp;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ClothappApplication {

    public static void main(String[] args) {
        SpringApplication.run(ClothappApplication.class, args);
    }
}

However, when I run my Spring Boot application, it provides me with an AbstractMethodError. I've read some other SO questions, and apparently some class has inappropriately changed since it was last compiled. Could anyone provide some help?

Exception in thread "main" java.lang.AbstractMethodError: org.apache.logging.log4j.core.config.ConfigurationFactory.getConfiguration(Lorg/apache/logging/log4j/core/config/ConfigurationSource;)Lorg/apache/logging/log4j/core/config/Configuration;
    at org.apache.logging.log4j.core.config.ConfigurationFactory$Factory.getConfiguration(ConfigurationFactory.java:472)
    at org.apache.logging.log4j.core.config.ConfigurationFactory$Factory.getConfiguration(ConfigurationFactory.java:442)
    at org.apache.logging.log4j.core.config.ConfigurationFactory.getConfiguration(ConfigurationFactory.java:254)
    at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:419)
    at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:138)
    at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:147)
    at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:41)
    at org.apache.logging.log4j.LogManager.getContext(LogManager.java:175)
    at org.apache.commons.logging.LogFactory$Log4jLog.<clinit>(LogFactory.java:199)
    at org.apache.commons.logging.LogFactory$Log4jDelegate.createLog(LogFactory.java:166)
    at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:109)
    at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:99)
    at org.springframework.boot.SpringApplication.<clinit>(SpringApplication.java:198)
    at app.clothapp.ClothappApplication.main(ClothappApplication.java:10)

Thank you.

回答1:

There will be more than one transitive dependency on spring-boot-starter-logging. For example:

  • spring-boot-starter-security depends on spring-boot-starter
  • spring-boot-starter depends on spring-boot-starter-logging

You can run gradle dependencies to confirm.

In order to exlcude a dependency from everywhere, use:

configurations {
    all*.exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
}

Spring suggest including the dependency on spring-boot-starter and then excluding the logger from there, something like:

compile('org.springframework.boot:spring-boot-starter') {
    exclude module: "spring-boot-starter-logging"
}

But I have found that not all Spring dependencies are so well behaved, so the above sometimes fails when there are explicit dependencies on Spring logging elsewhere.