Spring Cache

缓存简介

比如我们要查询数据,我们先从缓冲中查找有没有,如果没有再调用该方法,并且加入到缓冲中,下次调用的时候直接从缓冲中去数据。

导读

未使用缓存

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:cache="http://www.springframework.org/schema/cache" xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.2.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

	<context:annotation-config />
	<context:component-scan base-package="com.tony.test" />
</beans>
//执行任务类
@Component
public class Worker {
	
	public void longTask(final long id) {
		System.out.printf("长任务ID %d...%n", id);

	}

	public void shortTask(final long id) {
		System.out.printf("短任务ID %d...%n", id);
	}
}

//Main方法测试
public class App {
	 public static void main(final String[] args) {
		    final String xmlFile = "classpath*:*/spring.xml";
		    try (ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlFile)) {

		      final Worker worker = (Worker)context.getBean(Worker.class);
		      worker.longTask(1);
		      worker.longTask(1);
		      worker.longTask(1);
		      worker.longTask(2);
		      worker.longTask(2);
		    }
		  }
}

测试结果


未使用缓存每次都会进行数据调用

使用缓存

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:cache="http://www.springframework.org/schema/cache" xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.2.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

	<context:annotation-config />
	<context:component-scan base-package="com.tony.test" />
	<cache:annotation-driven />
	<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
		<property name="caches">
			<set>
				<bean
					class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"
					p:name="task" />
			</set>
		</property>
	</bean>
         
</beans>
//执行任务类
@Component
public class Worker {
	@Cacheable("task")
	public void longTask(final long id) {
		System.out.printf("长任务ID %d...%n", id);

	}

	public void shortTask(final long id) {
		System.out.printf("短任务ID %d...%n", id);
	}
}

//Main方法测试
public class App {
	 public static void main(final String[] args) {
		    final String xmlFile = "classpath*:*/spring.xml";
		    try (ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlFile)) {

		      final Worker worker = (Worker)context.getBean(Worker.class);
		      worker.longTask(1);
		      worker.longTask(1);
		      worker.longTask(1);
		      worker.longTask(2);
		      worker.longTask(2);

                      worker.shortTask(1);
		      worker.shortTask(1);
		    }
		  }
}

测试结果


上面测试可以看到,定义了@Cacheable("task"),只打印《长任务ID 1…》和《长任务ID 2…》各执行一次,说明缓存起作用了。

简单概述

`` 这个代表启用缓存,默认会调用一个`cacheManager `的缓存管理器.它是通过`org.springframework.cache.support.SimpleCacheManager` 来实现管理。 在这里我们定义了一个`p:name="task"`,这个和我们`Woker`中的`@Cacheable("task")`是对应的 。使用了`org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean`来进行处理。 如下`ConcurrentMapCacheFactoryBean` 基于map来实现存储的。 ```java public class ConcurrentMapCacheFactoryBean implements FactoryBean, BeanNameAware, InitializingBean {
private String name = "";

private ConcurrentMap<Object, Object> store;

private boolean allowNullValues = true;

private ConcurrentMapCache cache;


/**
 * Specify the name of the cache.
 * <p>Default is "" (empty String).
 */
public void setName(String name) {
	this.name = name;
}

/**
 * Specify the ConcurrentMap to use as an internal store
 * (possibly pre-populated).
 * <p>Default is a standard {@link java.util.concurrent.ConcurrentHashMap}.
 */
public void setStore(ConcurrentMap<Object, Object> store) {
	this.store = store;
}

/**
 * Set whether to allow {@code null} values
 * (adapting them to an internal null holder value).
 * <p>Default is "true".
 */
public void setAllowNullValues(boolean allowNullValues) {
	this.allowNullValues = allowNullValues;
}

@Override
public void setBeanName(String beanName) {
	if (!StringUtils.hasLength(this.name)) {
		setName(beanName);
	}
}

    //重写InitializingBean 中的afterPropertiesSet方法  
@Override
public void afterPropertiesSet() {
	this.cache = (this.store != null ? new ConcurrentMapCache(this.name, this.store, this.allowNullValues) :
			new ConcurrentMapCache(this.name, this.allowNullValues));
}


@Override
public ConcurrentMapCache getObject() {
	return this.cache;
}

@Override
public Class<?> getObjectType() {
	return ConcurrentMapCache.class;
}

@Override
public boolean isSingleton() {
	return true;
}

}


####基于代理存储cache数据
```java
public static void main(final String[] args) {
		final String xmlFile = "classpath*:*/spring.xml";
		try (ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlFile)) {

			final Worker worker = (Worker) context.getBean(Worker.class);
			
			System.out.println(worker.getClass().getCanonicalName());
			
		}
	}

上面getCanonicalName方法打印结果:com.tony.test.Worker E n h a n c e r B y S p r i n g C G L I B EnhancerBySpringCGLIB EnhancerBySpringCGLIB9bdaf924 ,当我们调用Worker的,其实是调用的一个代理对象,当调用方法上面加上cache之后,代理对象将cache存储起来,下次请求过来之后直接返回cache的value值。

这个文章讲的不错

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值