经典的无法拦截内部方法调用案例:
package com.imooc.service; import com.imooc.config.ApplicationContextHolder; import org.springframework.aop.framework.AopContext; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Component; import java.util.Arrays; import java.util.List; @Component public class MenuService { @Cacheable(cacheNames = {"menu"}) public List<String> getMenuList(){ System.out.println(""); System.out.println("mock:get from db"); return Arrays.asList("article","comment","admin"); } public List<String> getRecommends(){ return this.getMenuList(); } }
Ps:不会启动AOP: 因为是通过 this 调用,哪怕该方法上有切面注解,但获取不到Bean的原因,所以注解也会失效。
解决方案:通过代理来调用该方法,而不是通过 this 来调用。
package com.imooc.service; import com.imooc.config.ApplicationContextHolder; import org.springframework.aop.framework.AopContext; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Component; import java.util.Arrays; import java.util.List; @Component public class MenuService { @Cacheable(cacheNames = {"menu"}) public List<String> getMenuList(){ System.out.println(""); System.out.println("mock:get from db"); return Arrays.asList("article","comment","admin"); } public List<String> getRecommends(){ MenuService proxy = ApplicationContextHolder.getContext().getBean(MenuService.class); return proxy.getMenuList(); } }
package com.imooc.config; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; @Component public class ApplicationContextHolder implements ApplicationContextAware { private static ApplicationContext ctx; public static ApplicationContext getContext() { return ctx; } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { ctx = applicationContext; } }