53

@Cacheable同じクラス内からメソッドを呼び出そうとしています。

@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(findPerson(id));
   }
   return list;
}

findPersonsからの結果もキャッシュされることを期待していますが、@Cacheableアノテーションは無視され、findPersonメソッドは毎回実行されます。

私はここで何か間違ったことをしていますか、それともこれは意図されていますか?

4

3 に答える 3

57

これは、Springのキャッシュ、トランザクション関連機能を処理するためのプロキシの作成方法が原因です。これは、Springがそれを処理する方法の非常に良いリファレンスです-トランザクション、キャッシング、およびAOP:Springでのプロキシの使用法を理解する

つまり、セルフコールは動的プロキシをバイパスし、動的プロキシロジックの一部であるキャッシングやトランザクションなどの横断的関心事もバイパスされます。

修正は、AspectJのコンパイル時またはロード時のウィービングを使用することです。

于 2012-08-24T20:22:21.983 に答える
29

これは、同じクラス内でメソッド呼び出しをわずかに使用するだけの小さなプロジェクトに対して私が行うことです。同僚には苦痛に見えるかもしれないので、コード内のドキュメントを強くお勧めします。しかし、テストが簡単で、シンプルで、すばやく達成でき、本格的なAspectJインストルメンテーションを使用できません。ただし、より頻繁に使用する場合は、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;
    }
}
于 2015-12-04T14:42:45.120 に答える
2

Grails Spring Cacheプラグインを使用している場合、回避策はドキュメントに記載されています。Grailsアプリでこの問題が発生しましたが、残念ながら、受け入れられた回答はGrailsでは使用できないようです。解決策は醜いです、私見ですが、それは機能します。

サンプルコードはそれをよく示しています。

class ExampleService {
    def grailsApplication

    def nonCachedMethod() {
        grailsApplication.mainContext.exampleService.cachedMethod()
    }

    @Cacheable('cachedMethodCache')
    def cachedMethod() {
        // do some expensive stuff
    }
}

exampleService.cachedMethod()を独自のサービスとメソッドに置き換えるだけです。

于 2013-05-31T19:13:39.547 に答える