6

@Cacheableを使用して作成したAOPプロキシがSpring 3.1.1の依存関係注入を中断した場合、私はうんざりしました。私のシナリオは次のとおりです。@Cacheable breaks DependencyInjection

実装されたメソッドで@Cacheableを使用してこのインターフェイスを実装するクラスとインターフェイスがあります。

例インタフェース:

public interface ImgService { 
    public byte[] getImage(String name); 
} 

実装例:

public class ImgServiceImpl implements ImgService { 

    @Cacheable(cacheName = "someCache") 
    public byte[] getImage(String name){//TODO}; 

    protected String someOtherMethod(){//}; 
} 

Iはまた、JUnitテストクラスに持っ - インタフェースと一の実装を注入いずれか

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "classpath*:META-INF/spring.xml" }) 
public class ImgServiceTest { 

    @Inject 
    private ImgService; 
} 

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "classpath*:META-INF/spring.xml" }) 
public class ImgServiceImplTest { 

    @Inject 
    private ImgServiceImpl; 
} 

インターフェイスの依存関係注入が正常に動作します。しかし、2番目のテストクラスでインプリメンテーションを実行すると、"自動依存依存の注入が失敗しました"というメッセージが表示されます。私はそれをデバッグすることができました。ClassUtils.isAssignableValue()は、誤って目的のタイプをプロキシクラスと比較しています。 DefaultListableBeanFactoryによって呼び出されます。私は@Cacheableアノテーションを実装されたメソッドから削除し、それを他の保護された/プライベートなメソッドに追加すると、依存関係の注入が再びうまく機能するということは、他人には分かりません。これはバグですか、この状況を処理する正しい方法は何でしょうか?

+0

ここに1つ以上である:これは次のように私の実装・テスト・クラスは今見え

@SuppressWarnings({"unchecked"}) public static <T> T getTargetObject(Object proxy, Class<T> targetClass) { if (AopUtils.isJdkDynamicProxy(proxy)) { try { return (T) ((Advised)proxy).getTargetSource().getTarget(); } catch (Exception e) { return null; } } else { return (T) proxy; } } 

:私はorg.springframework.aop.framework.Advisedクラスの実装に基づいてプロキシからターゲットオブジェクトを抽出しようと簡単な方法を実装しました良いリファレンス - http://blog.springsource.org/2012/05/23/understanding-proxy-usage-in-spring/ –

答えて

3

OKなので、ここで私はようやく思いついた解決策があります。

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "classpath*:META-INF/spring.xml" }) 
public class ImgServiceImplTest { 

    @Inject 
    private ImgService imgService; 

    private ImgServiceImpl imgServiceImpl; 

    @PostConstruct 
    public void setUp() { 
     imgServiceImpl = getTargetObject(imgService, ImgServiceImpl.class); 
    } 


} 
10

これはバグではなく、JDKの動的プロキシをAOPの実装に使用することによる予期しない副作用です。

キャッシュ可能なメソッドImgServiceImplの呼び出しはすべて、タイプImgServiceの動的プロキシを経由する必要があるため、ImgServiceImplのフィールドにこの依存関係を挿入する方法はありません。

@Cacheable、この場合には有効になりませんので、あなたがprivateまたはprotected法、射出作品へ@Cacheableを移動する - だけpublic方法は、プロキシベースのAOPを使用してadvicedすることができます。

したがって、注入するフィールドをImgServiceとして宣言するか、proxy-target-class = "true"を使用する代わりに、ターゲットクラスベースのプロキシを使用するようにSpringを設定する必要があります。

さらに別のオプションは、SpringをAspectJ-based AOP implementation(コンパイル時またはロード時の織りが必要)を使用するように設定することです。

Springが提供するすべてのAOPベースの機能(トランザクション、セキュリティ、非同期実行、キャッシュ、カスタムアスペクトなど)に適用されます。

も参照してください:

+0

答えをありがとう。 ClassUtilsメソッドがこれを処理しないことは、私にはまだ奇妙に思えます。 – kpentchev

関連する問題