web-dev-qa-db-ja.com

Spring 3.1 @Cacheable-メソッドはまだ実行されています

here および here の説明に従ってSpring 3.1キャッシングを実装しようとしていますが、機能していないようです。 @cacheableとマークされています。何が悪いのですか?

独自の構成ファイルを使用してjunitテストケースに移動し、他のアプリケーションから分離しましたが、問題は引き続き発生します。関連ファイルは次のとおりです。

Spring-test-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:cache="http://www.springframework.org/schema/cache"
   xmlns:p="http://www.springframework.org/schema/p"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
<cache:annotation-driven />

<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcache"/>
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
      p:config-location="classpath:ehcache.xml"/>
</beans>

ehcache.xml

<ehcache>
<diskStore path="Java.io.tmpdir"/>
<cache name="cache"
       maxElementsInMemory="100"
       eternal="false"
       timeToIdleSeconds="120"
       timeToLiveSeconds="120"
       overflowToDisk="true"
       maxElementsOnDisk="10000000"
       diskPersistent="false"
       diskExpiryThreadIntervalSeconds="120"
       memoryStoreEvictionPolicy="LRU"/>

</ehcache>

MyTest.Java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:spring-test-servlet.xml"})
@Component
public class MyTest extends TestCase {

    @Test
    public void testCache1(){
        for(int i = 0; i < 5; i++){
            System.out.println("Calling someMethod...");
            System.out.println(someMethod(0));
        }
    }

    @Cacheable("testmethod")
    private int someMethod(int val){
        System.out.println("Not from cache");
        return 5;
    }
}

関連するPomエントリ:(spring-version = 3.1.1.RELEASE)

    <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache-core</artifactId>
        <version>2.5.1</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
    </dependency>

テストを実行すると、Springはキャッシュがエラーなしで初期化されているように見えるいくつかのデバッグメッセージを出力します

DEBUG: config.ConfigurationHelper - No CacheManagerEventListenerFactory class specified. Skipping...
DEBUG: ehcache.Cache - No BootstrapCacheLoaderFactory class specified. Skipping...
DEBUG: ehcache.Cache - CacheWriter factory not configured. Skipping...
DEBUG: config.ConfigurationHelper - No CacheExceptionHandlerFactory class specified. Skipping...
DEBUG: store.MemoryStore - Initialized net.sf.ehcache.store.MemoryStore for cache
DEBUG: disk.DiskStorageFactory - Failed to delete file cache.data
DEBUG: disk.DiskStorageFactory - Failed to delete file cache.index
DEBUG: disk.DiskStorageFactory - Matching data file missing (or empty) for index file. Deleting index file /var/folders/qg/xwdvsg6x3mx_z_rcfvq7lc0m0000gn/T/cache.index
DEBUG: disk.DiskStorageFactory - Failed to delete file cache.index
DEBUG: ehcache.Cache - Initialised cache: cache
DEBUG: config.ConfigurationHelper - CacheDecoratorFactory not configured. Skipping for 'cache'.
DEBUG: config.ConfigurationHelper - CacheDecoratorFactory not configured for defaultCache. Skipping for 'cache'.

しかし、デバッグ出力では、someMethodへのメソッド呼び出しとsomeMethod内部からの印刷ステートメントの間のキャッシュチェックが毎回表示されないことが示されています。

行方不明のものはありますか?

28
Andy Miller

http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/cache.html から

プロキシモード(デフォルト)では、プロキシ経由で着信する外部メソッド呼び出しのみがインターセプトされます。つまり、実質的に、ターゲットオブジェクト内のメソッドが、ターゲットオブジェクトの別のメソッドを呼び出す呼び出されたメソッドが@Cacheableでマークされている場合でも、実行時に実際のキャッシングは行われません-この場合、aspectjモードの使用を検討してください。

そして

メソッドの可視性と@Cacheable/@CachePut/@CacheEvict

プロキシを使用する場合は、@Cacheアノテーションは、public visibilityを使用するメソッドに対してのみです。

  1. 同じターゲットオブジェクトでsomeMethodを自己起動します。
  2. 君の @Cacheableメソッドはパブリックではありません。
80
Lee Chee Kiam

アノテーションで参照している名前と一致するキャッシュを定義する必要があります(「testmethod」)。そのキャッシュのehcache.xmlにもエントリを作成します。

2
pap

Lee Chee Kiamに加えて:これは、バイパスされた(注釈付きではない)メソッド呼び出しをわずかに使用する小規模プロジェクトの私の解決策です。 DAOは単にプロキシとして自身に挿入され、単純なメソッド呼び出しの代わりにそのプロキシを使用して独自のメソッドを呼び出します。したがって、@ Cacheableは、複雑なインストルメンテーションを行わずに考慮されます。

同僚には奇妙に見えるかもしれないので、コード内のドキュメントは強く提供されています。しかし、そのテストは簡単で、簡単で、すぐに達成でき、本格的なAspectJインストゥルメンテーションを節約できます。ただし、より頻繁に使用する場合は、Lee Chee Kiamが行ったように、AspectJソリューションにもアドバイスします。

@Service
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
class PersonDao {

    private final PersonDao _personDao;

    @Autowired
    public PersonDao(PersonDao personDao) {
        _personDao = personDao;
    }

    @Cacheable(value = "defaultCache", key = "#id")
    public Person findPerson(int id) {
        return getSession().getPerson(id);
    }

    public List<Person> findPersons(int[] ids) {
        List<Person> list = new ArrayList<Person>();
        for (int id : ids) {
            list.add(_personDao.findPerson(id));
        }
        return list;
    }
}
1
Mario Eis