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

2019-06-17 21:06发布

我试图调用@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得到了每次执行的方法。

我在这里做得不对,或这是故意的吗?

Answer 1:

这是因为代理是在春季处理缓存,交易相关功能创建的方式。 这是Spring是如何处理它一个很好的参考- 交易,缓存和AOP:在春天的了解代理的使用

简言之,自呼叫绕过动态代理和任何横切关注点像缓存,交易等,这是动态代理逻辑的一部分也被绕过。

解决方法是使用AspectJ的编译时间或加载时编织。



Answer 2:

下面是同一类的我的小项目做的唯一方法边际使用什么叫。 在代码文档强烈advidsed,因为它可能看起来strage给同事。 但它容易测试,简单,快速的实现和备件我完全成熟的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;
    }
}


Answer 3:

对于使用Grails的弹簧缓存插件任何人, 一种解决方法是在文档中的描述 。 我有一个Grails应用这个问题,但不幸的是公认的答案似乎是不可用于Grails的。 该解决方案是丑陋的,恕我直言,但它的作品。

该代码示例演示得好:

class ExampleService {
    def grailsApplication

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

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

只需用自己的服务和方法取代exampleService.cachedMethod()。



文章来源: Spring cache @Cacheable method ignored when called from within the same class