Spring Boot进阶:原理、实战与面试题分析
上QQ阅读APP看书,第一时间看更新

3.4.2 确保类内方法调用能够应用代理

请注意,并不是所有场景下Spring AOP都是能够生效的,例如,在代码清单3-24所示的ServiceImpl中,直接调用添加了@Transactional注解的handleData()方法时,事务机制并不会生效。

代码清单3-24 在类内方法上使用代理代码示例

public class ServiceImpl implements Service {
    @Override
    public void performBusiness(){
        //事务无效
        this.handleData();
    }

    @Transactional
    public void handleData()  {
    }
}

这是因为Spring AOP是通过代理实现的,而无论是JDK代理还是CGLIB代理,其运行机制是对某一个外部的接口或实现类进行代理,像上述代码中直接调用ServiceImpl类内的方法是不会应用代理的。

解决这一问题的常见方法就是使用上下文对象AopContext,示例代码如代码清单3-25所示。

代码清单3-25 AopContext使用代码示例

public class ServiceImpl implements Service {
    public void performBusiness(){
        //从AopContext中获取代理对象
        ((Service)AopContext.currentProxy()).handleData();
    }

    @Transactional
    public void handleData()  {
    }
}

这里我们直接从AopContext中获取代理对象。当然,上述代码生效的前提是确保ProxyFactoryBean的exposeProxy属性被设置为true,正如我们在3.2.3节中讨论的那样。