Spring AopContext.currentProxy 遇到 JDK动态代理

在实际开发中,我们经常需要在同一个类中嵌套调用事物方法,由于spring aop原理,只有在代理类调用层面的方法才会解析事物,方法内部嵌套调用,无法解析事物注解。所以这时我们就需要修改嵌套调用方式,用AopContext.currentProxy 获取当前类的代理类来调用嵌套调用的方法,这样spring aop就会解析方法事物注解标记。但是如果当前类实现了接口,spring默认会使用JDK动态代理,依赖注入需要改成接口注入方式,AopContext.currentProxy 需要强转成接口,这时非接口方法就无法识别。

在spring中,如果bean没有实现接口,默认会采用CGLIB代理,代理类就是当前类的子类;如果bean实现了接口,spring默认会采用JDK动态代理,这个代理类实际是接口的实现类。JDK动态代理 是spring推荐的注入方式,因为他遵循了面向接口编程的模式,开发中更加灵活。下面的代码中可以看到两种代理在依赖注入时的区别。

构建一个接口

public interface ITransactionService {
public void outTransaction();
public void innerTransaction();
}

构建一个接口实现

@Service
public class TransactionService implements ITransactionService{
@Transactional
public void outTransaction() {
System.out.println("*******************outTransaction start****************");
((ITransactionService) AopContext.currentProxy()).innerTransaction();
System.out.println("*******************outTransaction end****************");
// throw new NullPointerException("报错啦");
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void innerTransaction() {
System.out.println("*************innerTransaction***********");
}
}

构建一个测试类

public class TransactionTest extends BaseTest {
//TransactionService 实现接口时如下注入
@Autowired
private ITransactionService transactionService;
//TransactionService 未实现接口如下注入
//@Autowired
//private ITransactionService transactionService;
@Test
public void outTransaction(){
transactionService.outTransaction();
}
}

但是实际开发中,偶尔需要打破这种模式,如果 ITransactionService 接口中并不包含innerTransaction 方法,AopContext.currentProxy 将无法获取该方法。幸好spring 支持通过aop:config 强制使用CGLIB ,这样就解决了AopContext.currentProxy 获取不到非接口函数的问题。

aop:config proxy-target-class 设置为true

修改注入方式

public class TransactionTest extends BaseTest {
@Autowired
private TransactionService transactionService;
@Test
public void outTransaction(){
transactionService.outTransaction();
}
}

修改AopContext.currentProxy强制类型指向实现类

((TransactionService) AopContext.currentProxy()).innerTransaction();​​​​​​​

 

你可能感兴趣的:(笔记)