@Cacehable
当第一次查询数据库后,将数据添加到缓存中,第二次查询数据库时可以直接走缓存,不必再走数据库
注意!!!如果在本类中调用此注解标记的方法,并不会走缓存!!!
不调用的原因
为什么缓存没有被正常创建?? 因为@Cacheable 是使用AOP 代理实现的 ,通过创建内部类来代理缓存方法(JDK动态代理、CGLib代理),这样就会导致一个问题,类内部的方法调用类内部的缓存方法不会走代理,不会走代理,就不能正常创建缓存,所以每次都需要去调用数据库。
@Cacheable 的一些注意点 1、因为@Cacheable 由AOP 实现,所以,如果该方法被其它注解切入,当缓存命中的时候,则其它注解不能正常切入并执行,@Before 也不行,当缓存没有命中的时候,其它注解可以正常工作
2、@Cacheable 方法不能进行内部调用,否则缓存无法创建
@Cacheable标注的方法,如果其所在的类实现了某一个接口,那么该方法也必须出现在接口里面,否则cache无效。
具体的原因是, Spring把实现类装载成为Bean的时候,会用代理包装一下,所以从Spring Bean的角度看,只有接口里面的方法是可见的,其它的都隐藏了,自然课看不到实现类里面的非接口方法,@Cacheable不起作用。
解决办法:把待cache的方法移到接口里面。
另外衍生两个小问题:
-
@Cacheable放接口里面可以吗?答案是:不行。
-
如果某一个Bean并没有实现任何接口,@Cacheable标注的方法有什么要求? 答案是public即可。这种Bean也被Spring产生代理,是CGlib代理,通过动态生成子类继承并重写其方法,所以 看得到的只有public方法。
本质是Spring代理的问题,很多的基础设施可能都会遇到类似的问题。比如安全,事务,日志等等。