在java同一个类中,一个方法调用另外一个有注解(比如@Async,@Transational)的方法,注解不生效解决方案。

在Java中,如果在同一个类中直接调用另一个带有注解的方法,比如@Async或@Transactional,注解通常不会生效。这是因为这些注解通常是通过Spring的AOP(面向方面编程)来实现的,而AOP代理对象只能拦截外部对目标对象的方法调用,而不能拦截内部方法调用。

原因

Spring在处理这些注解时,会生成一个代理对象来管理事务、异步操作等。如果你在同一个类中直接调用带有这些注解的方法,本质上是在调用同一个对象的方法,而不是通过代理对象调用的,因此这些注解不会生效。

解决方案

1. 使用AOP注解的方法放到另一个Bean中

一种方法是将带有这些注解的方法移到另一个Spring管理的Bean中,然后通过依赖注入调用该Bean的方法。

例如:

java 复制代码
@Service
public class MyService {

    @Autowired
    private AnotherService anotherService;

    public void myMethod() {
        anotherService.asyncMethod();
    }
    
}

@Service
public class AnotherService {

    @Async
    public void asyncMethod() {
        // 你的异步代码
    }
    
}

2. 使用AOP自调用

如果不想将方法移到另一个Bean中,可以通过Spring应用上下文来获取自身的代理对象并调用方法。

例如:

java 复制代码
@Service
public class MyService {

    @Autowired
    private ApplicationContext applicationContext;

    public void myMethod() {
        MyService self = applicationContext.getBean(MyService.class);
        self.asyncMethod();
    }

    @Async
    public void asyncMethod() {
        // 你的异步代码
    }
}

3. 使用@ConfigurableSpring AOP

这种方法相对复杂一些,可以在类上使用@Configurable注解,然后在Spring配置中启用AspectJ代理。

java 复制代码
@Configurable
public class MyService {

    public void myMethod() {
        asyncMethod();
    }

    @Async
    public void asyncMethod() {
        // 你的异步代码
    }
}

在Spring配置中启用AspectJ代理:

xml 复制代码
xml复制代码
<bean id="configurableAnnotationProcessor"
      class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

<context:load-time-weaver aspectj-weaving="on"/>

总结

在同一个类中直接调用带有AOP注解的方法时,这些注解通常不会生效。可以通过将方法移到另一个Bean、通过Spring上下文获取自身代理对象或使用@Configurable注解等方式解决这个问题。

完整的测试代码:

java 复制代码
package com.minp.admin.task.standingbook;

import lombok.extern.log4j.Log4j2;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

/**
 * @功能描写: 测试异步注解任务
 * @Author ****
 * @Versions 1.0
 * @Data: 2024/6/4 10:32
 * @项目名称: ****
 */
@Component
@Log4j2
public class TestAsyncAnnotationTask {

    private final ApplicationContext applicationContext;

    public TestAsyncAnnotationTask(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public void testAsyncAnnotationTask() {
        log.info("测试异步注解任务--开始");
        log.info("当前线程名称-{}", Thread.currentThread().getName());
        test1();
        applicationContext.getBean(TestAsyncAnnotationTask.class).test2();
    }

    @Async
    public void test1() {
        log.info("调用了test1");
        log.info("当前线程名称-{}", Thread.currentThread().getName());
    }

    @Async
    public void test2() {
        log.info("调用了test2");
        log.info("当前线程名称-{}", Thread.currentThread().getName());
    }

}
相关推荐
笃行3506 小时前
SQLServer数据迁移之后,那张报表还能不能秒出
后端
LucianaiB6 小时前
别再被 AI 骗了:我把腾讯云 4 个 Skill 做成了个「AI 打假侦探」,过程的一个小配置坑惨了我
后端
candyTong7 小时前
Claude Code 如何恢复一段会话
后端·架构·ai编程
En^_^Joy8 小时前
Django项目配置全攻略:settings配置文件
后端·python·django
IT_陈寒11 小时前
Python线程池吞了异常还不告诉我,这谁顶得住啊
前端·人工智能·后端
小强库计算机毕业设计11 小时前
SpringBoot+Vue3 学生宿舍管理系统实战
java·spring boot·后端·vue·学生宿舍管理系统
小狼18311 小时前
实践6|SDD 实战:AI 写的规格被推翻了四次
后端·claude
篮框坏了11 小时前
"DeepSeek Harness 实测:一毛钱干三活,但默认配置是个坑"
后端·ai编程
jobBridge2111 小时前
大模型到底是怎么"想"的?我把 Transformer 拆开,发现它其实是个"接词狂魔"
人工智能·后端·编程语言
唐青枫12 小时前
看懂内存地址之后,才算真正入门 Zig:指针、切片与实战
后端