从同一个类中调用时,忽略Spring缓存@Cacheable方法

Dav*_*hao 36 spring caching spring-cache

我正在尝试@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;
}
Run Code Online (Sandbox Code Playgroud)

并希望结果findPersons也被缓存,但@Cacheable注释被忽略,并且findPerson每次都执行方法.

我在这里做错了什么,或者这是有意的吗?

Bij*_*men 39

这是因为创建代理的方式用于处理Spring中的缓存,事务相关功能.这是Spring如何处理它的一个很好的参考 - Transactions,Caching和AOP:理解Spring中的代理使用

简而言之,自我调用会绕过动态代理,并且还会绕过作为动态代理逻辑一部分的任何交叉问题,如缓存,事务等.

修复是使用AspectJ编译时间或加载时间编织.


Mar*_*Eis 18

以下是我对同一类中只有少量方法调用的小项目所做的工作.强烈建议使用代码内文档,因为它可能会让同事感到惊讶.但它易于测试,简单,快速实现,并使我完全成熟的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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 因为要将PersonDao注入PersonDao,您需要在实例化PersonDao之前先拥有一个实例:)要解决此问题,可以使用存根代理([见文档](http://docs.spring.io/spring/docs/current/ spring-framework-reference / htmlsingle /#beans-java-scoped-proxy)被创建,注入并随后填充与注入的相同PersonDao实例。如此,PersonDao可以保存自身的实例,并包装到存根代理中。[那样容易:)](http://memeguy.com/photos/images/playing-portal-co-op-this-is-the-main-argument-with-my-roommate-40939.jpg)不要不知道那是否足够清楚...:D (2认同)