[英]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()
。
使用Spring將bean引用注入bean,甚至是同一個bean,就像對任何其他bean引用一樣。 無需特殊操作。
這種變量的存在明確地在類設計中承認該類期望以某種方式代理。 這不一定是壞事,因為aop可以改變打破類合同的行為。
bean引用通常用於接口,並且該接口甚至可以是自引用內部方法的不同接口。
把事情簡單化。 那種方式就是瘋狂。 :-)
更重要的是,確保語義有意義。 這樣做的需要可能是一個代碼氣味,這個類混合了多個職責,最好地分解成單獨的bean。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.