threeperson
发布于 2016-03-19 / 0 阅读
0
0

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

```

<aop:config expose-proxy="true" 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();

```


评论