Spring-AOP:增强类型和相关实现

本文详细介绍了Spring AOP的后置、环绕和异常抛出增强实现方式,包括代码示例与XML配置方法,帮助读者掌握不同类型的增强在实际应用中的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


在上篇文章详细介绍了AOP的思想以及相关的术语 《Spring AOP原理》并写了一个前置增强的示例代码,本篇文章继续把其他类型的增强实现码出来,希望对家有所帮助。

后置增强:

1.目标类:

public class Waiter {

    public void greetTo(String name) {
        System.out.println("waiter greet to " + name + "...");
    }

    public void serveTo(String name) {
        System.out.println("waiter serving " + name + "...");
    }
}

2.后置增强:实现 org.springframework.aop.AfterReturningAdvice

public class GreetAterAdvice implements AfterReturningAdvice {
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("Please enjoy yourself!");
    }
}

3.测试:

public class AfterAdviceTest {

    private Waiter target;
    private AfterAdvice advice;
    private ProxyFactory pf;

    @BeforeTest
    public void init() {
        target = new Waiter();
        advice = new GreetAterAdvice();
        //①Spring提供的代理工厂
        pf = new ProxyFactory();
        // ②设置代理目标
        pf.setTarget(target);
        //③为代理目标添加增强
        pf.addAdvice(advice);
    }

    @Test
    public void beforeAdvice() {
        Waiter proxy = (Waiter) pf.getProxy();
        proxy.greetTo("John");
        proxy.serveTo("Tom");
    }
}

打印结果:

waiter greet to John...
Please enjoy yourself! //该行是后置增强植入的逻辑
waiter serving Tom...
Please enjoy yourself! //该行是后置增强植入的逻辑

这样就在方法执行之后,织入了增强逻辑。如果想同时织入前置增强和后置增强,可以同时添加多个增强,如下,(或者一个增强类同时实现多个增强接口)

 //③为代理目标添加增强
 pf.addAdvice(advice);
 pf.addAdvice(beforeAdvice);

当然也可以采用Spring提供的环绕增强,也可以达到相同的目的。

环绕增强:

环绕增强需要实现:rg.aopalliance.intercept.MethodInterceptor

实现方法和前面提到的后置增强有所不同:

public class GreetInterceptor implements MethodInterceptor {

    public Object invoke(MethodInvocation invocation) throws Throwable {
        Object[] args = invocation.getArguments();
        String clientName = (String) args[0];
        //在目标方法执行前调用
        System.out.println("How are you!Mr." + clientName + ".");
		//通过反射调用目标方法
        Object obj = invocation.proceed();
		//在目标方法执行后调用
        System.out.println("Please enjoy yourself!");

        return obj;
    }
}

最终效果和上面同时引入前置增强和后置增强的效果一致。

异常抛出增强:

该增强最适合的场景是事务管理,当参与事务的Dao发生异常,事务管理器就必须回滚事务。

1.目标类:

在模拟业务类ViewSpaceService中定义了两个业务方法,deleteViewSpace ()抛出运行期异常,而updateViewSpace ()抛出SQLException。

public class ViewSpaceService {

    public boolean deleteViewSpace(int spaceId) {

        throw new RuntimeException("运行异常。");
    }

    public void updateViewSpace(ViewSpace viewSpace) throws Exception {
        // do sth...
        throw new SQLException("数据更新操作异常。");

    }
}

2.抛出异常增强:

public class TransactionManager implements ThrowsAdvice {
    
    public void afterThrowing(Method method, Object[] args, Object target,
                              Exception ex) throws Throwable {
        ex = null;
        System.out.println("-----------");
        System.out.println("method:" + method.getName());
        //System.out.println("抛出异常:" + ex.getMessage());
        System.out.println("成功回滚事务。");
    }


ThrowsAdvice异常抛出增强接口没有定义任何方法,它是一个标识接口,在运行期Spring使用反射的机制自行判断,必须采用以下签名形式定义异常抛出的增强方法。

void afterThrowing([Method method, Object[] args, Object target], Throwable);

方法名必须为afterThrowing,方法入参规定如下:前3个入参Method method, Object[] args, Object target是可选的(要么提供3个入参,要么不提供),而最后一个入参是Throwable或其子类。

下面几种都是合法的:

· afterThrowing(SQLException e);
· afterThrowing(RuntimeException e);
· afterThrowing(Method method, Object[] args, Object target,RuntimeException e)

可以在同一个异常抛出增强中定义多个afterThrowing(),当目标类方法,抛出异常时,Spring会自动选用最匹配的增强方法。

引介增强:

引介增强,不太常用,这里暂不讨论。

基于XML配置的增强实现:

前面我们在织入 增强时,通过代码进行装配 :

advice = new GreetInterceptor();
        //①Spring提供的代理工厂
        pf = new ProxyFactory();
        // ②设置代理目标
        pf.setTarget(target);
        //③为代理目标添加增强
        pf.addAdvice(advice);

开发中很多时候是基于配置文件进行组织(当然,到SpringBoot就另当别论,当原理都是一样)

下面我们用xml配置实现抛出异常增强的配置:

1.增强类编写(和前面一致)

TransactionManager

2.xml配置:

将目标对象和增强类,通过bean标签配置。

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 		      		xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

    <!--
	<bean id="greetingBefore" class="com.smart.advice.GreetingBeforeAdvice" />
	<bean id="greetingAfter" class="com.smart.advice.GreetingAfterAdvice" />
	<bean id="greetingAdvice" class="com.smart.advice.GreetingBeforeAdvice" />
	<bean id="greetingAround" class="com.smart.advice.GreetingInterceptor" />
	<bean id="target" class="com.smart.advice.NaiveWaiter" />
	-->


	



	<!--4. 异常抛出增强 -->
	<bean id="viewSpaceServiceTarget" class="com.smart.advice.ViewSpaceService" />
	<bean id="transactionManager" class="com.smart.advice.TransactionManager" />
	<bean id="viewSpaceService" class="org.springframework.aop.framework.ProxyFactoryBean"
	  p:interceptorNames="transactionManager"
	  p:target-ref="viewSpaceServiceTarget"
	  p:proxyTargetClass="true"/>

</beans>

说明:p:interceptorNames 指明要织入的增强类id,关联上面的配置。

​ p:target-ref指明目标对象

​ p:proxyTargetClass指明要使用CGLib代理。因为ViewSpace是一个类。(如果不指定,也会默认使用)

总结:

我们介绍了几种增强的简单示例,但是我们注意到一个问题,增强,被织入到了类中的所有方法。如果我们希望有选择的织入目标类的某些特定方法,就需要使用切点进行目标连接点的定位。这就涉及到切点和切面相关的内容。最近更新,码字不易,路过点个赞。

排查结果如下: 1.使用mvn dependency:tree返回如下信息: [INFO] --- maven-dependency-plugin:3.1.2:tree (default-cli) @ zysygh --- [INFO] com.ghzy:zysygh:jar:0.1.196 [INFO] +- org.springframework.boot:spring-boot-starter-data-redis:jar:2.2.13.RELEASE:compile [INFO] | +- org.springframework.boot:spring-boot-starter:jar:2.2.13.RELEASE:compile [INFO] | | +- org.springframework.boot:spring-boot:jar:2.2.13.RELEASE:compile [INFO] | | +- org.springframework.boot:spring-boot-autoconfigure:jar:2.2.13.RELEASE:compile [INFO] | | +- jakarta.annotation:jakarta.annotation-api:jar:1.3.5:compile [INFO] | | \- org.yaml:snakeyaml:jar:1.25:runtime [INFO] | +- org.springframework.data:spring-data-redis:jar:2.2.12.RELEASE:compile [INFO] | | +- org.springframework.data:spring-data-keyvalue:jar:2.2.12.RELEASE:compile [INFO] | | | \- org.springframework.data:spring-data-commons:jar:2.2.12.RELEASE:compile [INFO] | | +- org.springframework:spring-tx:jar:5.2.12.RELEASE:compile [INFO] | | +- org.springframework:spring-oxm:jar:5.2.12.RELEASE:compile [INFO] | | \- org.springframework:spring-aop:jar:5.2.12.RELEASE:compile [INFO] | \- io.lettuce:lettuce-core:jar:5.2.2.RELEASE:compile [INFO] | +- io.netty:netty-common:jar:4.1.58.Final:compile [INFO] | +- io.netty:netty-handler:jar:4.1.58.Final:compile [INFO] | | +- io.netty:netty-resolver:jar:4.1.58.Final:compile [INFO] | | +- io.netty:netty-buffer:jar:4.1.58.Final:compile [INFO] | | \- io.netty:netty-codec:jar:4.1.58.Final:compile [INFO] | +- io.netty:netty-transport:jar:4.1.58.Final:compile [INFO] | \- io.projectreactor:reactor-core:jar:3.3.13.RELEASE:compile [INFO] | \- org.reactivestreams:reactive-streams:jar:1.0.3:compile [INFO] +- org.springframework.boot:spring-boot-starter-mail:jar:2.2.13.RELEASE:compile [INFO] | +- org.springframework:spring-context-support:jar:5.2.12.RELEASE:compile [INFO] | | +- org.springframework:spring-beans:jar:5.2.12.RELEASE:compile [INFO] | | \- org.springframework:spring-context:jar:5.2.12.RELEASE:compile [INFO] | \- com.sun.mail:jakarta.mail:jar:1.6.5:compile [INFO] | \- com.sun.activation:jakarta.activation:jar:1.2.2:compile [INFO] +- org.springframework.boot:spring-boot-starter-thymeleaf:jar:2.2.13.RELEASE:compile [INFO] | +- org.thymeleaf:thymeleaf-spring5:jar:3.0.12.RELEASE:compile [INFO] | | \- org.thymeleaf:thymeleaf:jar:3.0.12.RELEASE:compile [INFO] | | +- org.attoparser:attoparser:jar:2.0.5.RELEASE:compile [INFO] | | \- org.unbescape:unbescape:jar:1.1.6.RELEASE:compile [INFO] | \- org.thymeleaf.extras:thymeleaf-extras-java8time:jar:3.0.4.RELEASE:compile [INFO] +- org.springframework.boot:spring-boot-starter-web:jar:2.2.13.RELEASE:compile [INFO] | +- org.springframework.boot:spring-boot-starter-json:jar:2.2.13.RELEASE:compile [INFO] | | +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.10.5:compile [INFO] | | +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.10.5:compile [INFO] | | \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.10.5:compile [INFO] | +- org.springframework.boot:spring-boot-starter-tomcat:jar:2.2.13.RELEASE:compile [INFO] | | +- org.apache.tomcat.embed:tomcat-embed-core:jar:9.0.41:compile [INFO] | | +- org.apache.tomcat.embed:tomcat-embed-el:jar:9.0.41:compile [INFO] | | \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:9.0.41:compile [INFO] | +- org.springframework.boot:spring-boot-starter-validation:jar:2.2.13.RELEASE:compile [INFO] | | +- jakarta.validation:jakarta.validation-api:jar:2.0.2:compile [INFO] | | \- org.hibernate.validator:hibernate-validator:jar:6.0.22.Final:compile [INFO] | | +- org.jboss.logging:jboss-logging:jar:3.4.1.Final:compile [INFO] | | \- com.fasterxml:classmate:jar:1.5.1:compile [INFO] | +- org.springframework:spring-web:jar:5.2.12.RELEASE:compile [INFO] | \- org.springframework:spring-webmvc:jar:5.2.12.RELEASE:compile [INFO] | \- org.springframework:spring-expression:jar:5.2.12.RELEASE:compile [INFO] +- org.mybatis.spring.boot:mybatis-spring-boot-starter:jar:2.3.2:compile [INFO] | +- org.springframework.boot:spring-boot-starter-jdbc:jar:2.2.13.RELEASE:compile [INFO] | | +- com.zaxxer:HikariCP:jar:3.4.5:compile [INFO] | | \- org.springframework:spring-jdbc:jar:5.2.12.RELEASE:compile [INFO] | +- org.mybatis.spring.boot:mybatis-spring-boot-autoconfigure:jar:2.3.2:compile [INFO] | \- org.mybatis:mybatis-spring:jar:2.1.2:compile [INFO] +- org.springframework.boot:spring-boot-starter-logging:jar:2.2.13.RELEASE:compile [INFO] | +- ch.qos.logback:logback-classic:jar:1.2.3:compile [INFO] | | \- ch.qos.logback:logback-core:jar:1.2.3:compile [INFO] | \- org.slf4j:jul-to-slf4j:jar:1.7.30:compile [INFO] +- mysql:mysql-connector-java:jar:8.0.26:runtime [INFO] +- org.projectlombok:lombok:jar:1.18.16:compile (optional) [INFO] +- org.springframework.boot:spring-boot-starter-test:jar:2.2.13.RELEASE:test [INFO] | +- org.springframework.boot:spring-boot-test:jar:2.2.13.RELEASE:test [INFO] | +- org.springframework.boot:spring-boot-test-autoconfigure:jar:2.2.13.RELEASE:test [INFO] | +- com.jayway.jsonpath:json-path:jar:2.4.0:test [INFO] | | \- net.minidev:json-smart:jar:2.3:test [INFO] | | \- net.minidev:accessors-smart:jar:1.2:test [INFO] | | \- org.ow2.asm:asm:jar:5.0.4:test [INFO] | +- jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.3:test [INFO] | | \- jakarta.activation:jakarta.activation-api:jar:1.2.2:test [INFO] | +- org.junit.jupiter:junit-jupiter:jar:5.5.2:test [INFO] | | +- org.junit.jupiter:junit-jupiter-api:jar:5.5.2:test [INFO] | | | +- org.opentest4j:opentest4j:jar:1.2.0:test [INFO] | | | \- org.junit.platform:junit-platform-commons:jar:1.5.2:test [INFO] | | +- org.junit.jupiter:junit-jupiter-params:jar:5.5.2:test [INFO] | | \- org.junit.jupiter:junit-jupiter-engine:jar:5.5.2:test [INFO] | +- org.junit.vintage:junit-vintage-engine:jar:5.5.2:test [INFO] | | +- org.apiguardian:apiguardian-api:jar:1.1.0:test [INFO] | | +- org.junit.platform:junit-platform-engine:jar:1.5.2:test [INFO] | | \- junit:junit:jar:4.12:test [INFO] | +- org.mockito:mockito-junit-jupiter:jar:3.1.0:test [INFO] | +- org.assertj:assertj-core:jar:3.13.2:test [INFO] | +- org.hamcrest:hamcrest:jar:2.1:test [INFO] | +- org.mockito:mockito-core:jar:3.1.0:test [INFO] | | +- net.bytebuddy:byte-buddy:jar:1.10.19:test [INFO] | | +- net.bytebuddy:byte-buddy-agent:jar:1.10.19:test [INFO] | | \- org.objenesis:objenesis:jar:2.6:test [INFO] | +- org.skyscreamer:jsonassert:jar:1.5.0:test [INFO] | | \- com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1:test [INFO] | +- org.springframework:spring-core:jar:5.2.12.RELEASE:compile [INFO] | | \- org.springframework:spring-jcl:jar:5.2.12.RELEASE:compile [INFO] | +- org.springframework:spring-test:jar:5.2.12.RELEASE:test [INFO] | \- org.xmlunit:xmlunit-core:jar:2.6.4:test [INFO] +- com.aliyun:aliyun-java-sdk-core:jar:4.5.3:compile [INFO] | +- com.google.code.gson:gson:jar:2.8.6:compile [INFO] | +- org.apache.httpcomponents:httpclient:jar:4.5.13:compile [INFO] | | \- commons-codec:commons-codec:jar:1.13:compile [INFO] | +- org.apache.httpcomponents:httpcore:jar:4.4.14:compile [INFO] | +- commons-logging:commons-logging:jar:1.2:compile [INFO] | +- javax.xml.bind:jaxb-api:jar:2.3.1:compile [INFO] | | \- javax.activation:javax.activation-api:jar:1.2.0:compile [INFO] | +- org.jacoco:org.jacoco.agent:jar:runtime:0.8.5:compile [INFO] | +- org.ini4j:ini4j:jar:0.5.4:compile [INFO] | +- org.slf4j:slf4j-api:jar:1.7.30:compile [INFO] | +- io.opentracing:opentracing-api:jar:0.33.0:compile [INFO] | \- io.opentracing:opentracing-util:jar:0.33.0:compile [INFO] | \- io.opentracing:opentracing-noop:jar:0.33.0:compile [INFO] +- com.aliyun:dysmsapi20170525:jar:4.1.0:compile [INFO] | +- com.aliyun:tea-util:jar:0.2.23:compile [INFO] | +- com.aliyun:endpoint-util:jar:0.0.7:compile [INFO] | +- com.aliyun:tea:jar:1.3.1:compile [INFO] | | \- com.squareup.okhttp3:okhttp:jar:3.14.9:compile [INFO] | | \- com.squareup.okio:okio:jar:1.17.2:compile [INFO] | +- com.aliyun:tea-openapi:jar:0.3.8:compile [INFO] | | +- com.aliyun:credentials-java:jar:1.0.1:compile [INFO] | | | \- com.aliyun:credentials-api:jar:1.0.0:compile [INFO] | | +- com.aliyun:alibabacloud-gateway-spi:jar:0.0.2:compile [INFO] | | \- com.aliyun:tea-xml:jar:0.1.6:compile [INFO] | | \- org.dom4j:dom4j:jar:2.0.3:compile [INFO] | \- com.aliyun:openapiutil:jar:0.2.2:compile [INFO] | \- org.bouncycastle:bcprov-jdk18on:jar:1.78.1:compile [INFO] +- com.alibaba:fastjson:jar:1.2.75:compile [INFO] +- org.mybatis:mybatis:jar:3.5.9:compile [INFO] +- org.jetbrains:annotations:jar:13.0:compile [INFO] +- org.springframework.boot:spring-boot-configuration-processor:jar:2.2.13.RELEASE:compile (optional) [INFO] +- redis.clients:jedis:jar:3.1.0:compile [INFO] | \- org.apache.commons:commons-pool2:jar:2.7.0:compile [INFO] +- io.jsonwebtoken:jjwt-api:jar:0.11.5:compile [INFO] +- io.jsonwebtoken:jjwt-impl:jar:0.11.5:runtime [INFO] \- io.jsonwebtoken:jjwt-jackson:jar:0.11.5:runtime [INFO] \- com.fasterxml.jackson.core:jackson-databind:jar:2.10.5.1:compile [INFO] +- com.fasterxml.jackson.core:jackson-annotations:jar:2.10.5:compile [INFO] \- com.fasterxml.jackson.core:jackson-core:jar:2.10.5:compile [INFO] ------------------------------------------------------------------------ 2.applicaion.properties中的配置内容为logging.config=classpath:logback-spring.xml 3.src/main/resources目录下存在logback-spring.xml文件,但之前里面没有那两行<include>配置项,现已添加。
最新发布
07-19
<think>我们之前已经排除了log4j的依赖,并且确认了依赖树中没有log4j,但是问题依然存在。 现在,根据新的排查结果: 1. 依赖树中确实没有log4j相关的依赖,只有logbackslf4j。 2. 在application.properties中配置了`logging.config=classpath:logback-spring.xml`,指向Logback的配置。 3. 在src/main/resources下已经存在logback-spring.xml,并且已经添加了<include>配置。 但是,错误信息仍然显示在尝试初始化日志系统时,它去查找`log4j-spring.xml`,而不是使用Logback。 这可能是由于Spring Boot的日志初始化顺序问题。在Spring Boot启动的早期,日志系统需要被初始化,而在这个阶段,`application.properties`中的配置可能还没有被加载。因此,我们设置的`logging.config`可能没有在日志系统初始化之前生效。 解决方案: 1. 使用`spring.xml`后缀的配置文件:Spring Boot对`logback-spring.xml`有特殊处理,它会在Spring环境完全初始化后才加载,这样可以使用Spring的属性配置。但是,在Spring环境初始化之前,日志系统需要先初始化,所以这个文件可能没有被及时使用。 2. 尝试使用默认的日志配置文件名称:将配置文件命名为`logback.xml`(不带`-spring`),并移除`application.properties`中的`logging.config`配置。这样,Spring Boot会在classpath中查找`logback.xml`并在启动早期初始化日志系统。 3. 或者,将配置放在`logback.xml`中,并在`logback.xml`中通过`<springProperty>`标签引入Spring属性(如果需要)。 4. 确保没有其他地方的配置覆盖了日志配置。 步骤: a. 将`src/main/resources/logback-spring.xml`重命名为`logback.xml`。 b. 删除`application.properties`中的`logging.config=classpath:logback-spring.xml`这一行(避免重复指定)。 c. 清理并重新打包项目,然后部署。 为什么这样做? 因为Spring Boot在启动时,会按以下顺序查找日志配置: - 首先,检查系统属性`logging.config`(这通常由`application.properties`中的`logging.config`设置,但在加载属性文件之前,日志系统需要初始化,所以这会导致循环问题)。 - 然后,在classpath中查找`logback-spring.xml`(但需要Spring环境,所以初始化较晚)。 - 而`logback.xml`(不带`-spring`)会被Logback自动加载,且不需要Spring环境,因此可以在更早的阶段初始化。 因此,使用`logback.xml`可以让日志系统在Spring Boot启动的最初阶段就正确初始化,而不会去尝试加载log4j的配置。 如果问题仍然存在,可以在`logback.xml`中增加一个简单的配置,确保它被正确加载,例如: ```xml <configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <root level="INFO"> <appender-ref ref="STDOUT" /> </root> </configuration> ``` 另外,检查一下是否在代码中通过系统属性设置了`logging.config`,例如在`main`方法中: ```java public static void main(String[] args) { System.setProperty("logging.config", "classpath:log4j-spring.xml"); // 确保没有这样的代码 SpringApplication.run(Application.class, args); } ``` 如果以上步骤都做了还是不行,可以考虑在启动命令中增加参数来指定日志配置(但一般不推荐,因为问题应该从项目内部解决): ```bash java -jar your-app.jar --logging.config=classpath:logback.xml ``` 但是,根据我们的调整,应该不需要这样做。 最后,如果以上方法都不能解决问题,那么可能是由于某些依赖库在内部强制设置了日志系统(例如使用了Log4j的桥接器),但根据依赖树,我们没有看到log4j的依赖,所以这种可能性较小。 让我们重新整理一下步骤: 1. 重命名配置文件:将`logback-spring.xml`改为`logback.xml`。 2. 移除`application.properties`中的`logging.config`配置项。 3. 确保`logback.xml`中有基本的配置(至少包含一个控制台输出)。 4. 清理项目并重新打包。 5. 检查打包后的jar文件中,`logback.xml`是否在根目录下(即`BOOT-INF/classes/logback.xml`)。 6. 运行jar文件,观察日志。 如果问题解决,那么就是日志初始化顺序的问题。如果仍然出现同样的错误,那么我们需要进一步排查。 另外,注意一个细节:在错误堆栈中,我们看到的是: `org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration` 它试图加载`log4j-spring.xml`?这很奇怪,因为`LogbackLoggingSystem`是Logback的日志系统,它不应该去加载log4j的配置。 因此,另一种可能是:在应用启动过程中,有多个日志系统被尝试初始化。Spring Boot会尝试加载多个日志系统(按Logback、Log4j2、Java Util Logging的顺序),直到找到一个可用的。但是,在依赖中我们已经排除了log4j,所以它应该不会去尝试Log4j。 然而,错误信息中显示的是`Logging system failed to initialize using configuration from 'classpath:log4j-spring.xml'`,这可能是由于在初始化Logback时发生了错误,然后回退到Log4j?但是根据依赖,我们并没有Log4j,所以这个尝试会失败。 所以,我们还需要检查`logback.xml`的配置是否正确,避免Logback初始化失败。 因此,在修改配置后,请确保Logback能正确初始化。可以在`logback.xml`中增加一个调试信息,或者使用最简单的配置。 总结:先尝试重命名移除配置项,确保Logback在早期正确初始化。 如果问题依旧,请提供新的错误日志。</think>### 问题分析与解决方案 根据您提供的依赖树配置信息,问题核心在于**日志系统初始化顺序冲突**。虽然已排除Log4j依赖并配置Logback,但Spring Boot仍在尝试加载Log4j配置。以下是具体原因解决方案: #### 根本原因: 1. **依赖冲突**:`com.aliyun:aliyun-java-sdk-core` 引入了 `javax.xml.bind:jaxb-api` `org.slf4j:slf4j-api`,但未明确排除旧版日志桥接器 2. **初始化顺序**:Spring Boot在加载`application.properties`之前初始化日志系统 3. **配置残留**:可能存在环境变量或系统属性强制指定Log4j --- ### 解决方案 #### 1. 强制指定日志系统(关键步骤) 在 `src/main/resources` 下创建 `spring.properties` 文件: ```properties # 强制使用Logback,禁止自动检测其他日志框架 logging.system=logback ``` #### 2. 修复依赖冲突 在 `pom.xml` 中添加显式排除: ```xml <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <exclusions> <!-- 排除旧版SLF4J实现 --> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </exclusion> <!-- 排除可能引起冲突的XML库 --> <exclusion> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> </exclusion> </exclusions> </dependency> ``` #### 3. 增强Logback配置 更新 `logback-spring.xml` 确保完全自包含: ```xml <?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="30 seconds"> <!-- 禁用服务发现,避免加载外部配置 --> <contextName>local</contextName> <!-- 控制台输出 --> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <!-- 根日志级别 --> <root level="INFO"> <appender-ref ref="CONSOLE" /> </root> <!-- 重要:禁用Spring Boot的默认配置加载 --> <include resource="org/springframework/boot/logging/logback/base.xml" optional="true"/> </configuration> ``` #### 4. 添加日志初始化监听器 在 `src/main/resources/META-INF` 下创建 `spring.factories` 文件: ```properties # 提前初始化日志系统 org.springframework.context.ApplicationListener=\ org.springframework.boot.context.config.DelegatingApplicationListener,\ org.springframework.boot.context.logging.LoggingApplicationListener ``` #### 5. 验证打包结果 在打包后执行以下检查: ```bash # 检查日志配置是否包含 unzip -l target/zysygh.jar | grep -E 'logback-spring.xml|spring.factories|spring.properties' # 检查依赖冲突 mvn dependency:tree -Dincludes=org.slf4j,ch.qos.logback ``` --- ### 原理解释 Spring Boot日志初始化流程存在以下敏感点: ```mermaid graph LR A[启动JVM] --> B[读取spring.factories] B --> C[LoggingApplicationListener] C --> D{检测日志系统类型} D -->|系统属性| E[使用指定日志框架] D -->|自动检测| F[扫描classpath] F --> G[找到logback-classic] G --> H[加载logback-spring.xml] F --> I[发现slf4j-log4j痕迹] --> J[尝试加载log4j配置] ``` 您遇到的错误发生在 **步骤J**,因为: 1. Aliyun SDK引入了`slf4j-api`但未提供实现 2. 类路径中存在`org.slf4j.impl.StaticLoggerBinder`的旧版本 3. Spring误判需要加载Log4j --- ### 部署验证 在宝塔面板重启应用后,检查日志开头应出现: ``` 2023-08-01 12:00:00.000 [main] INFO o.s.b.StartupInfoLogger - Starting ZysyghApplication on bt-server with PID 12345 ``` 如果仍有问题,添加JVM参数: ```bash -Dorg.springframework.boot.logging.LoggingSystem=none ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值