@EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true)实例

@EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true)实例

报错:

java.lang.IllegalStateException: Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available, and ensure that AopContext.currentProxy() is invoked in the same thread as the AOP invocation context.

分析与建议

1. 简要解释报错原因

该错误是由于在AOP(面向切面编程)上下文中无法找到当前代理对象导致的。通常是因为Advised接口的exposeProxy属性未设置为true,或者AopContext.currentProxy()方法调用的线程与AOP调用上下文的线程不一致。

2. 原因详细分析
  • exposeProxy属性未设置:默认情况下,Spring AOP不会将当前代理对象暴露给用户代码。如果需要在切面中访问当前代理对象,必须显式地设置exposeProxy属性为true
  • 线程不一致AopContext.currentProxy()方法只能在AOP调用的同一个线程中使用。如果在不同的线程中调用该方法,会抛出IllegalStateException
3. 修复建议
  • 设置exposeProxy属性为true

    @Configuration
    @EnableAspectJAutoProxy(exposeProxy = true)
    public class AppConfig {
        // 其他配置
    }
    
  • 确保在同一个线程中调用AopContext.currentProxy()

    import org.springframework.aop.framework.AopContext;
    
    @Aspect
    public class MyAspect {
        @Around("execution(* com.example.service.*.*(..))")
        public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
            // 确保在同一个线程中调用
            Object proxy = AopContext.currentProxy();
            // 你的业务逻辑
            return```
    
    

@EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true)

分析与建议

1. 简要解释报错原因

java.lang.ClassCastException: com.sun.proxy.$Proxy44 cannot be cast to org.com.transaction.service.UserServiceImpl1 表示你尝试将一个由 Java 动态代理生成的代理对象($Proxy44)强制转换为 UserServiceImpl1 类型。这通常发生在使用了 Spring AOP 时,代理对象默认是基于接口的动态代理,而不是具体的实现类。

2. 原因复杂描述
  • 动态代理机制:Spring AOP 默认使用 JDK 动态代理,生成的代理类实现所有被代理类的接口,而不是继承被代理类。
  • 类型不匹配:当你尝试将代理对象直接转换为具体的实现类时,由于类型不匹配,会抛出 ClassCastException
  • 配置问题:可能是配置文件或注解配置不当,导致代理对象没有正确生成或注入。
3. 修复建议

根据上述分析,以下是几种可能的修复方法:

方法一:使用接口类型

如果你的服务实现类实现了某个接口,可以改为使用接口类型进行引用。

public interface UserService {
    void accountAddMoney();
    Account createUser(Account user);
    void createOtherInfo(Book book);
}

public class UserServiceImpl1 implements UserService, AopProxyC8a<UserServiceImpl1> {
    // 实现逻辑
}

// 在使用时
UserService userService = (UserService) context.getBean("userService");
userService.createUser(new Account());
方法二:使用 @EnableAspectJAutoProxy(proxyTargetClass = true)

如果需要使用 CGLIB 代理(针对没有接口的情况),可以在配置类中启用 CGLIB 代理。

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AppConfig {
    // 配置 Bean
}
方法三:使用 AopContext.currentProxy() 获取当前代理对象

如果你确实需要在方法内部获取当前代理对象,可以使用 AopContext.currentProxy() 方法。但需要注意,这需要在配置类中启用 exposeProxy

@Configuration
@EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true)
public class AppConfig {
    // 配置 Bean
}

然后在 UserServiceImpl1 中使用 AopContext.currentProxy()

import org.aopalliance.aop.Advice;
import org.springframework.aop.framework.AopContext;
import org.springframework.transaction.annotation.Transactional;

@Service
@Slf4j
public class UserServiceImpl1 implements UserService1, AopProxyC8a<UserServiceImpl1> {

    @Autowired
    private UserDao userDao;

    public void accountAddMoney() {
        userDao.addMoney();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Account createUser(Account user) {
        Account user1 = userDao.createUser(user);
        // self() 返回当前代理对象,createOtherInfo 会单独开一个事务,被AOP拦截处理
        Integer id = user1.getId();
        log.info("id:{}", id);
        Book book = new Book(1, "java", "c8a", 1, id);
        ((UserServiceImpl1) AopContext.currentProxy()).createOtherInfo(book);
        // this 是当前对象
        //this.createOtherInfo(book);
        log.info("执行完毕");
        return user;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createOtherInfo(Book book) {
        userDao.createOtherInfo(book);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值