簡體   English   中英

Spring bean如何檢測它本身是否已包裝在AOP代理中?

[英]How can a Spring bean detect if it itself has been wrapped in an AOP proxy?

每當執行標記有@Transactional注釋的DAO方法時,我們使用Spring的TransactionInterceptor使用ThreadLocal設置一些數據庫分區信息。 我們需要它能夠將查詢路由到不同的數據庫分區。

這適用於大多數DAO方法:

// this causes the invoke method to set a thread-local with the host name of
// the database server the partition is on
@Transactional
public int deleteAll() throws LocalDataException {

問題是我們需要在DAO中引用DAO 代理對象本身。 通常我們必須在proxy-dao中傳遞調用者:

public Pager<Foo, Long> getPager(FooDao proxyDao) {

這看起來像代碼中的以下內容顯然是粗略的。

fooDao.getPager(fooDao);

問題是,當我們在FooDao內部時, this 不是我們需要的代理DAO。

是否有更好的機制讓bean發現它周圍有代理包裝器? 我看過Spring AOPUtils,但我看不到找到對象的代理。 我不想要isAopProxy(...)作為例子。 我還閱讀了Spring AOP文檔,但除非我實現自己希望避免的AOP本機代碼,否則我無法在那里看到解決方案。

我懷疑我可以使用ApplicationContextAware實用程序bean和setProxyDao(...)方法將DAO注入其中,但這似乎也是一種黑客攻擊。 我可以檢測代理的任何其他想法,以便我可以在bean本身內使用它嗎? 謝謝你的幫助。

考慮到AspectJ編譯時間或加載時間編織對你來說,這是一個與你所建議的一致的hacky解決方案:

沿着這些方向創建一個界面:

public interface ProxyAware<T> {
    void setProxy(T proxy);
}

讓你的Dao實現ProxyAware實現,現在創建一個帶有Ordered接口的BeanPostProcessor,最后運行,沿着這些方向:

public class ProxyInjectingBeanPostProcessor implements BeanPostProcessor, Ordered {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        if (AopUtils.isAopProxy((bean))){
            try {
                Object target = ((Advised)bean).getTargetSource().getTarget();
                if (target instanceof ProxyAware){
                    ((ProxyAware) target).setProxy(bean);
                }
            } catch (Exception e) {
                // ignore
            }
        }
        return bean;
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}

它很難看,但很有效。

Spring提供了一個方便的靜態實用程序AopContext.currentProxy()方法,它將一個代理返回給從中調用它的對象。

雖然使用它被認為是一種不好的做法,但在Java EE中也存在語義相同的方法: SessionContext.getBusinessObject()

我寫的這個工具方法和各種陷阱幾篇文章: 123

使用Spring將bean引用注入bean,甚至是同一個bean,就像對任何其他bean引用一樣。 無需特殊操作。

這種變量的存在明確地在類設計中承認該類期望以某種方式代理。 這不一定是壞事,因為aop可以改變打破類合同的行為。

bean引用通常用於接口,並且該接口甚至可以是自引用內部方法的不同接口。

把事情簡單化。 那種方式就是瘋狂。 :-)

更重要的是,確保語義有意義。 這樣做的需要可能是一個代碼氣味,這個類混合了多個職責,最好地分解成單獨的bean。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM