Spring MVC 中的缓存 - 可以使用自动装配进行查找吗?
Spring Cache in MVC - Possible to lookup with autowiring?
我看到当应用程序启动时,我的单例缓存已创建
DEBUG Creating CGLIB proxy: target source is SingletonTargetSource for
target object [com.abc.xyz.util.CacheUtil@14e3dd3] DEBUG Unable to
apply any optimizations to advised method: public java.util.Map
但是我如何使用自动装配查找值,因为当我尝试时,它不会命中创建的单例并创建 CacheUtil 的新实例。
CacheUtil.java [这个class用@Component注解]
public Map getSelectOptions(String codeType) {
System.out.println("Cache Breached!!!");
HashMap selectOpts = new HashMap();
Vector<MyTableDO> vCodeMap = null;
vCodeMap = MyTableDO.getCodesFromDatabase(codeType, "LookupCacheUtil");
if(vCodeMap == null || vCodeMap.size() == 0) return selectOpts;
vCodeMap.forEach(codeMap -> selectOpts.put(codeMap.getCodeValue(), codeMap.getCodeDesc()));
return selectOpts;
}
我的 spring 配置 xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.abc.xyz" />
<context:annotation-config />
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
<bean id="cacheUtil" class="com.abc.xyz.util.CacheUtil" />
</beans>
Class 调用缓存方法
@Autowired
@Qualifier("cacheUtil")
protected CacheUtil cacheUtil;
public Map getSelectOptions(String codeType) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyApplication.class);
//ctx.refresh();
CacheUtil lkp = (CacheUtil) ctx.getBean(CacheUtil.class);
ctx.close();
System.out.println("App Context lookupCacheUtil -"+lkp); // Not the same object of Spring Cache and comes to be new instance on every call
System.out.println("Autowired lookupCacheUtil -"+cacheUtil); // Always comes to be NULL
return lkp.getSelectOptions(codeType);
}
}
我的应用程序class
@SpringBootApplication
@EnableCaching
public class MyApplication extends SpringBootServletInitializer{
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(MyApplication.class);
}
@Override
public void onStartup(ServletContext container) {
XmlWebApplicationContext context = new XmlWebApplicationContext();
context.setConfigLocation("/WEB-INF/config/spring-servlet.xml");
//using servlet 3 api to dynamically create spring dispatcher servlet
ServletRegistration.Dynamic dispatcher = container.addServlet("spring", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(2);
dispatcher.addMapping("/");
}
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
经过详细的分析,我对Autowired的理解更加细腻了。多亏了这个link.
在我的例子中,我在表单 bean 上自动装配了 'CacheUtil'。看来表单 bean 没有被 spring 管理,或者至少在这种情况下是这样。相同的自动装配在由 Spring.
管理的控制器中正常工作
所以我通过从应用程序上下文中获取 CacheUtil 的 Spring 缓存 'Proxy' 版本来解决这个问题。下面的代码片段应该有所帮助(方法 getInstance()):
import org.springframework.beans.BeansException;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component("MyCache")
public class CacheUtil implements ApplicationContextAware{
private static ApplicationContext appContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// TODO Auto-generated method stub
appContext = applicationContext;
}
/**
* Method to fetch the shared instance of the Spring Cache Object that helps reach the
* Cache that resides in Application Context.
*
* @return Singleton shared instance of the Spring Cache Proxy of this class CacheUtil
*/
public static CacheUtil getInstance() {
CacheUtil appCache = appContext.getBean("MyCache", CacheUtil.class);
if(appCache != null) return appCache;
return new CacheUtil();
}
我看到当应用程序启动时,我的单例缓存已创建
DEBUG Creating CGLIB proxy: target source is SingletonTargetSource for target object [com.abc.xyz.util.CacheUtil@14e3dd3] DEBUG Unable to apply any optimizations to advised method: public java.util.Map
但是我如何使用自动装配查找值,因为当我尝试时,它不会命中创建的单例并创建 CacheUtil 的新实例。
CacheUtil.java [这个class用@Component注解]
public Map getSelectOptions(String codeType) {
System.out.println("Cache Breached!!!");
HashMap selectOpts = new HashMap();
Vector<MyTableDO> vCodeMap = null;
vCodeMap = MyTableDO.getCodesFromDatabase(codeType, "LookupCacheUtil");
if(vCodeMap == null || vCodeMap.size() == 0) return selectOpts;
vCodeMap.forEach(codeMap -> selectOpts.put(codeMap.getCodeValue(), codeMap.getCodeDesc()));
return selectOpts;
}
我的 spring 配置 xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.abc.xyz" />
<context:annotation-config />
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
<bean id="cacheUtil" class="com.abc.xyz.util.CacheUtil" />
</beans>
Class 调用缓存方法
@Autowired
@Qualifier("cacheUtil")
protected CacheUtil cacheUtil;
public Map getSelectOptions(String codeType) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyApplication.class);
//ctx.refresh();
CacheUtil lkp = (CacheUtil) ctx.getBean(CacheUtil.class);
ctx.close();
System.out.println("App Context lookupCacheUtil -"+lkp); // Not the same object of Spring Cache and comes to be new instance on every call
System.out.println("Autowired lookupCacheUtil -"+cacheUtil); // Always comes to be NULL
return lkp.getSelectOptions(codeType);
}
}
我的应用程序class
@SpringBootApplication
@EnableCaching
public class MyApplication extends SpringBootServletInitializer{
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(MyApplication.class);
}
@Override
public void onStartup(ServletContext container) {
XmlWebApplicationContext context = new XmlWebApplicationContext();
context.setConfigLocation("/WEB-INF/config/spring-servlet.xml");
//using servlet 3 api to dynamically create spring dispatcher servlet
ServletRegistration.Dynamic dispatcher = container.addServlet("spring", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(2);
dispatcher.addMapping("/");
}
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
经过详细的分析,我对Autowired的理解更加细腻了。多亏了这个link.
在我的例子中,我在表单 bean 上自动装配了 'CacheUtil'。看来表单 bean 没有被 spring 管理,或者至少在这种情况下是这样。相同的自动装配在由 Spring.
管理的控制器中正常工作所以我通过从应用程序上下文中获取 CacheUtil 的 Spring 缓存 'Proxy' 版本来解决这个问题。下面的代码片段应该有所帮助(方法 getInstance()):
import org.springframework.beans.BeansException;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component("MyCache")
public class CacheUtil implements ApplicationContextAware{
private static ApplicationContext appContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// TODO Auto-generated method stub
appContext = applicationContext;
}
/**
* Method to fetch the shared instance of the Spring Cache Object that helps reach the
* Cache that resides in Application Context.
*
* @return Singleton shared instance of the Spring Cache Proxy of this class CacheUtil
*/
public static CacheUtil getInstance() {
CacheUtil appCache = appContext.getBean("MyCache", CacheUtil.class);
if(appCache != null) return appCache;
return new CacheUtil();
}