@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);
}
}
1万+

被折叠的 条评论
为什么被折叠?



