8

アノテーションでマークされたDAOメソッドが実行されるたびに、Springを使用しTransactionInterceptorてデータベースパーティション情報を設定しています。これは、クエリを異なるデータベース パーティションにルーティングできるようにするために必要です。ThreadLocal@Transactional

これは、ほとんどの 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 の内部にいる場合、必要なプロキシ DAO でthisないことです。

Bean がプロキシ ラッパーを持っていることを検出するためのより良いメカニズムはありますか? Spring AOPUtilsを見てきましたが、オブジェクトのプロキシを見つける方法がわかりません。isAopProxy(...)たとえば、私はしたくありません。Spring AOPのドキュメントも読みましたが、回避したい独自の AOP ネイティブ コードを実装しない限り、解決策が見つかりません。

ApplicationContextAwareユーティリティー Bean とメソッドを使用して DAO 自体に注入できるのではないかと思いますがsetProxyDao(...)、それもハックのようです。Bean 自体からプロキシを利用できるようにプロキシを検出する方法はありますか? 助けてくれてありがとう。

4

3 に答える 3

6

AspectJのコンパイル時間またはロード時間の織り方がうまくいかないことを考慮して、あなたが提案したことに沿ったハッキーなソリューション:

次の行に沿ってインターフェイスを作成します。

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;
    }
}

それは醜いですが、動作します。

于 2012-07-16T19:41:21.273 に答える
3

Springを使用して、他のBean参照の場合と同じように、同じBeanであってもBean参照をBeanに注入します。特別なアクションは必要ありません。

このような変数の存在は、クラスが何らかの方法でプロキシされることを期待していることをクラス設計で明示的に確認します。aopはクラス契約を破る動作を変更する可能性があるため、これは必ずしも悪いことではありません。

Bean参照は通常、インターフェース用であり、そのインターフェースは、自己参照内部メソッド用の別のインターフェースである場合もあります。

単純にする。そのように狂気があります。:-)

さらに重要なのは、セマンティクスが理にかなっていることを確認することです。これを行う必要があるのは、クラスが複数の責任を混ぜ合わせて、別々のBeanに最もよく分解されているというコードの臭いである可能性があります。

于 2012-08-14T04:22:04.603 に答える