官术网_书友最值得收藏!

3.2.3 ProxyFactoryBean

JDK自帶的動態代理以及基于CGLIB的動態代理在Spring框架中都得到了應用,最典型的應用場景就是實現AOP。Spring專門提供了一個ProxyFactoryBean類用于手動創建對象代理,并將創建的代理對象作為目標對象的AOP代理。

ProxyFactoryBean提供了一組配置屬性用于指定代理的執行行為,比較常見的包括proxyTargetClass和exposeProxy。如果proxyTargetClass屬性為true,則僅使用CGLIB創建代理。如果該屬性未設置,那么有兩種情況:如果目標類實現了接口,則將使用JDK創建代理;反之,將使用CGLIB創建代理。而exposeProxy屬性用于設置是否將當前代理暴露給ThreadLocal。如果該屬性為true,那么開發人員可以使用AopContext.currentProxy()方法來獲取代理對象。

接下來,我們演示如何使用ProxyFactoryBean來創建和管理代理對象。我們繼續沿用3.1.2節中所介紹的案例場景?,F在讓我們為MethodBeforeAdvice接口提供一個實現類。顯然從命名上看,這個實現類是方法執行前通知的,如代碼清單3-11所示。

代碼清單3-11 MethodBeforeAdvice接口實現類代碼

public class AccountTransactionInterceptor implements MethodBeforeAdvice{
    private static final Logger LOGGER = Logger.getLogger(AccountTransactionInterceptor.class);

    @Override
    public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
        LOGGER.info("賬戶交易被攔截");
    }
}

接著,我們通過Java代碼創建一個通知,實現方式如代碼清單3-12所示。

代碼清單3-12 Advisor實現類代碼

@Bean
public Advisor accountServiceAdvisor() {
    AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
    pointcut.setExpression("execution(* com.springboot.aop.service.AccountService.doAccountTransaction(..))");
    return new DefaultPointcutAdvisor(pointcut, new AccountTransactionInterceptor());
}

最后,我們創建一個ProxyFactoryBean實例,并設置相關屬性,如代碼清單3-13所示。

代碼清單3-13 ProxyFactoryBean實例代碼

@Bean
public ProxyFactoryBean accountService(){
    ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
    proxyFactoryBean.setTarget(new AccountServiceImpl());
    proxyFactoryBean.addAdvisor(accountServiceAdvisor());
    proxyFactoryBean.setExposeProxy(true);
    return proxyFactoryBean;
}

注意,這里我們設置目標類為AccountService接口的實現類AccountServiceImpl,并把exposeProxy屬性設置為true。這樣,我們在AccountServiceImpl中就可以使用Spring AOP提供的AopContext.currentProxy()方法來獲取這個代理對象,示例代碼如代碼清單3-14所示。

代碼清單3-14 AccountService實現類代碼

public class AccountServiceImpl implements AccountService{
    ...
    @Override
    public boolean doAccountTransaction(Account source, Account dest, int amount) {
        ((AccountService)(AopContext.currentProxy())).doAccountTransaction(source, dest, amount);
        return true;
    }
}
主站蜘蛛池模板: 平顺县| 阳原县| 黄龙县| 庄浪县| 博爱县| 竹北市| 临海市| 贵阳市| 阿拉善左旗| 扶沟县| 榕江县| 金沙县| 略阳县| 弥勒县| 洱源县| 陇川县| 阳江市| 荣昌县| 化州市| 衡阳市| 博爱县| 开原市| 辛集市| 榕江县| 休宁县| 宾川县| 河源市| 五峰| 加查县| 邵阳市| 新龙县| 江山市| 普安县| 东乌珠穆沁旗| 抚宁县| 麻城市| 长武县| 新郑市| 加查县| 林口县| 边坝县|