Spring缓存机制实例代码

网友投稿 268 2023-02-18


Spring缓存机制实例代码

Spring的缓存机制非常灵活,可以对容器中任意Bean或者Bean的方法进行缓存,因此这种缓存机制可以在javaEE应用的任何层次上进行缓存。

Spring缓存底层也是需要借助其他缓存工具来实现,例如EhCache(Hibernate缓存工具),上层则以统一API编程。

要使用Spring缓存,需要以下三步

1.向Spring配置文件导入context:命名空间

2.在Spring配置文件启用缓存,具体是添加

3.配置缓存管理器,不同的缓存实现配置不同,如果是EhCache,需要先配置一个ehcache.xrPlNIyGml

例如

maxElementsInMemory="10000"

eternal="false"

timeToIdleSeconds="120"

timeToLiveSeconds="120"

maxElementsOnDisk="10000000"

diskExpiryThreadIntervalSeconds="120"

memoryStoreEvictionPolicy="LRU"/>

maxElementsInMemory="10000"

eternal="false"

overflowToDisk="true"

timeToIdleSeconds="300"

timeToLiveSeconds="600" />

上面的ehcache.xml配置了两个缓存区,Spring中的Bean将会缓存在这些缓存区中,一般的,Spring容器中有多少个Bean,就会在ehcache中定义多少个缓存区。

接着在Spring配置文件中配置缓存管理器如下,其中第一个Bean是一个工厂Bean,用来配置EhCache的CacheManager, 第二个Bean才是为Spring缓存配置的缓存管理器,所以将第一个Bean注入第二个Bean。

class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"

p:configLocation="classpath:ehcache.xml"

p:shared="false" />

class="org.springframework.cache.ehcache.EhCacheCacheManager"

p:cacheManager-ref="ehCacheManager" >

下面是一个完整的Spring配置,

xmlns:xsi="http://w3.org/2001/XMLSchema-instance"

xmlns:p="http://springframework.org/schema/p"

xmlns:cache="http://springframework.org/schema/cache"

xmlns:context="http://springframework.org/schema/context"

xsi:schemaLocation="http://springframework.org/schema/beans

http://springframework.org/schema/beans/spring-beans-4.0.xsd

http://springframework.org/schema/cache

http://springframework.org/schema/cache/spring-cache-4.0.xsd

http://springframework.org/schema/context

http://springframework.org/schema/context/spring-context-4.0.xsd">

base-package="com.service"/>

class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"

p:configLocation="classpath:ehcache.xml"

p:shared="false" />

class="org.springframework.cache.ehcache.EhCacheCacheManager"

p:cacheManager-ref="ehCacheManager" >

下面将以@Cacheable为例,演示Spring基于EhCache缓存的用法。 Cacheable用于修饰类或者方法,如果修饰类,则类中所有方法都会被缓存。

类级别的缓存

例如有如下Bean类,

@Service("userService")

@Cacheable(value="users")

public class UserServiceImpl implements UserService {

@Override

public User getUsersByNameAndAge(String name, int age) {

System.out.println("正在执行getUsersByNameAndAge()..");

return new User(name,age);

}

@Override

public User getAnotherUser(String name, int age) {

System.out.println("正在执行getAnotherUser()..");

return new User(name,age);

}

}

基于类的缓存,将会缓存类中的所有方法,缓存之后,程序调用该类实例的任何方法,只要传入的参数相同,Spring将不会真正执行该方法,而是直接根据传入的参数去查找缓存中的数据!

比如像下面这样使用缓存数据,

public static void test2() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserService us = ctx.getBean("userService", UserService.class);

User u1 = us.getUsersByNameAndAge("张三", 50);

//由于第二次调用userService方法时,使用了相同参数,那么真正的方法将不会执行,

//Spring将直接从缓存按参数查找数据

User u2 = us.getAnotherUser("张三", 50);

System.out.println(u1==u2);

}

输出结果,

正在执行getUsersByNameAndAge()..

true

可以看到,上面的getAnotherUser()并没有真正执行,因为传入的参数与之前的方法传入的参数相同,于是Spring直接从缓存区数据了。

上面的Bean类中的注解@Cacheable除了必选属性value之外,还有key, condition,, unless属性,后面三个都是用来设置Spring存储策略,对于基于类的缓存来说,Spring默认以方法传入的参数作为key去缓存中查找结果。

当然我们也可以修改key的策略,让Spring按照其他标准,比如按照第一个参数是否相同来作为key,在缓存中查找结果。

将上面的Bean类修改如下,

@Service("userService")

@Cacheable(value="users", key="#name")

public class UserServiceImpl implements UserService {

@Override

public User getUsersByNameAndAge(String name, int age) {

意味着我们传入相同的name,Spring就不会真正执行方法。只有name不同的时候,方法才会真正执行,例如下面,

public static void test2() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserService us = ctx.getBean("userService", UserService.class);

User u1 = us.getUsersByNameAndAge("张三", 50);

//将@Cacheable的key参数改为key="#name"之后,下面的方法将可以执行。

User u2 = us.getAnotherUser("李四", 50);

System.out.println(u1==u2);

}

可以看到这回getAnotherUser()方法得到执行了,

1 正在执行getUsersByNameAndAge()..

2 正在执行getAnotherUser()..

3 false

我们也可以设置condition属性,例如,

@Service("userService")

@Cacheable(value="users", condition="#age<100")

public class UserServiceImpl implements UserService {

@Override

public User getUsersByNameAndAge(String name, int age) {

那么对于下面的代码来说,两个方法都不会被缓存,Spring每次都是执行真正的方法取结果,

public static void test2() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserService us = ctx.getBean("userService", UserService.class);

User u1 = us.getUsersByNameAndAge("张三", 500);

User u2 = us.getAnotherUser("李四", 500);

System.out.println(u1==u2);

}

执行结果,

正在执行getUsersByNameAndAge()..

正在执行getAnotherUser()..

false

方法级别的缓存

方法级别的缓存则只会对方法起作用了,不同的方法可以设置不用的缓存区,例如下面这样,

@Service("userService")

public class UserServiceImpl implements UserService {

@Cacheable("users1")

@Override

public User getUsersByNameAndAge(String name, int age) {

System.out.println("正在执行getUsersByNameAndAge()..");

return new User(name,age);

}

@Cacheable("users2")

@Override

public User getAnotherUser(String name, int age) {

System.out.println("正在执行getAnotherUser()..");

return new User(name,age);

}

}

使用下面的测试代码,

public static void test2() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserService us = ctx.getBean("userService", UserService.class);

//第一次执行方法,方法将会真正执行并缓存

User u1 = us.getUsersByNameAndAge("张三", 500);

//虽然下面方法传入相同参数,但是因为这两个方法在不同的缓存区,所以无法使用缓存数据

User u2 = us.getAnotherUser("张三", 500);

System.out.println(u1==u2);

//上面已经缓存过,这里不会真正执行,直接使用缓存

User u3 = us.getAnotherUser("张三", 500);

System.out.println(u3==u2);

}

执行结果,

正在执行getUsersByNameAndAge()..

正在执行getAnotherUser()..

false

true

使用@CacheEvict清除缓存

被@CacheEvict修饰的方法可以用来清除缓存,使用@CacheEvict可以指定如下属性。

allEntries, 是否清空整个缓存区

beforeInvocation: 是否在执行方法之前清除缓存。默认是方法执行成功之后才清除。

condiition以及key, 与@Cacheable中一样的含义。

下面示范简单用啊,

@Service("userService")

@Cacheable("users")

public class UserServiceImpl implements UserService {

@Override

public User getUsersByNameAndAge(String name, int age) {

System.out.println("正在执行getUsersByNameAndAge()..");

return new User(name,age);

}

@Override

public User getAnotherUser(String name, int age) {

System.out.println("正在执行getAnotherUser()..");

return new User(name,age);

}

//指定根据name,age参数清楚缓存

@CacheEvict(value="users")

public void evictUser(String name, int age) {

System.out.println("--正在清空"+name+","+age+"对应的缓存--");

}

//指定清除user缓存区所有缓存的数据

@CacheEvict(value="users", allEntries=true)

public void evictAll() {

System.out.println("--正在清空整个缓存--");

}

}

下面是测试类,

public static void test2() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserService us = ctx.getBean("userService", UserService.class);

//系统会缓存两个方法

User u1 = us.getUsersByNameAndAge("张三", 500);

User u2 = us.getAnotherUser("李四",400);

//调用evictUser()方法清除缓冲区指定的数据

us.evictUser("李四", 400);

//前面清除了 李四, 400 的缓存,下面的方法返回的数据将会再次被缓存

User u3 = us.getAnotherUser("李四", 400);

System.out.println(us == u3); //false

//前面已经缓存了 张三, 500的数据,下面方法不会重新执行,直接取缓存中的数据

User u4 = us.getAnotherUser("张三", 500);

System.out.println(u1==u4); //输出true

//清空整个缓存

us.evictAll();

//由于整个缓存都已经被清空,下面的代码都会被重新执行

User u5 = us.getAnotherUser("张三", 500);

User u6 = us.getAnotherUser("李四", 400);

System.out.println(u1==u5); //输出false

System.out.println(u3==u6); //输出false

}

执行结果,

正在执行getUsersByNameAndAge()..

正在执行getAnotherUser()..

--正在清空李四,400对应的缓存--

正在执行getAnotherUser()..

false

true

--正在清空整个缓存--

正在执行getAnotherUser()..

正在执行getAnotherUser()..

false

false

总结

以上就是本文关于Spring缓存机制实例代码的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

maxElementsInMemory="10000"

eternal="false"

timeToIdleSeconds="120"

timeToLiveSeconds="120"

maxElementsOnDisk="10000000"

diskExpiryThreadIntervalSeconds="120"

memoryStoreEvictionPolicy="LRU"/>

maxElementsInMemory="10000"

eternal="false"

overflowToDisk="true"

timeToIdleSeconds="300"

timeToLiveSeconds="600" />

上面的ehcache.xml配置了两个缓存区,Spring中的Bean将会缓存在这些缓存区中,一般的,Spring容器中有多少个Bean,就会在ehcache中定义多少个缓存区。

接着在Spring配置文件中配置缓存管理器如下,其中第一个Bean是一个工厂Bean,用来配置EhCache的CacheManager, 第二个Bean才是为Spring缓存配置的缓存管理器,所以将第一个Bean注入第二个Bean。

class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"

p:configLocation="classpath:ehcache.xml"

p:shared="false" />

class="org.springframework.cache.ehcache.EhCacheCacheManager"

p:cacheManager-ref="ehCacheManager" >

下面是一个完整的Spring配置,

xmlns:xsi="http://w3.org/2001/XMLSchema-instance"

xmlns:p="http://springframework.org/schema/p"

xmlns:cache="http://springframework.org/schema/cache"

xmlns:context="http://springframework.org/schema/context"

xsi:schemaLocation="http://springframework.org/schema/beans

http://springframework.org/schema/beans/spring-beans-4.0.xsd

http://springframework.org/schema/cache

http://springframework.org/schema/cache/spring-cache-4.0.xsd

http://springframework.org/schema/context

http://springframework.org/schema/context/spring-context-4.0.xsd">

base-package="com.service"/>

class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"

p:configLocation="classpath:ehcache.xml"

p:shared="false" />

class="org.springframework.cache.ehcache.EhCacheCacheManager"

p:cacheManager-ref="ehCacheManager" >

下面将以@Cacheable为例,演示Spring基于EhCache缓存的用法。 Cacheable用于修饰类或者方法,如果修饰类,则类中所有方法都会被缓存。

类级别的缓存

例如有如下Bean类,

@Service("userService")

@Cacheable(value="users")

public class UserServiceImpl implements UserService {

@Override

public User getUsersByNameAndAge(String name, int age) {

System.out.println("正在执行getUsersByNameAndAge()..");

return new User(name,age);

}

@Override

public User getAnotherUser(String name, int age) {

System.out.println("正在执行getAnotherUser()..");

return new User(name,age);

}

}

基于类的缓存,将会缓存类中的所有方法,缓存之后,程序调用该类实例的任何方法,只要传入的参数相同,Spring将不会真正执行该方法,而是直接根据传入的参数去查找缓存中的数据!

比如像下面这样使用缓存数据,

public static void test2() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserService us = ctx.getBean("userService", UserService.class);

User u1 = us.getUsersByNameAndAge("张三", 50);

//由于第二次调用userService方法时,使用了相同参数,那么真正的方法将不会执行,

//Spring将直接从缓存按参数查找数据

User u2 = us.getAnotherUser("张三", 50);

System.out.println(u1==u2);

}

输出结果,

正在执行getUsersByNameAndAge()..

true

可以看到,上面的getAnotherUser()并没有真正执行,因为传入的参数与之前的方法传入的参数相同,于是Spring直接从缓存区数据了。

上面的Bean类中的注解@Cacheable除了必选属性value之外,还有key, condition,, unless属性,后面三个都是用来设置Spring存储策略,对于基于类的缓存来说,Spring默认以方法传入的参数作为key去缓存中查找结果。

当然我们也可以修改key的策略,让Spring按照其他标准,比如按照第一个参数是否相同来作为key,在缓存中查找结果。

将上面的Bean类修改如下,

@Service("userService")

@Cacheable(value="users", key="#name")

public class UserServiceImpl implements UserService {

@Override

public User getUsersByNameAndAge(String name, int age) {

意味着我们传入相同的name,Spring就不会真正执行方法。只有name不同的时候,方法才会真正执行,例如下面,

public static void test2() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserService us = ctx.getBean("userService", UserService.class);

User u1 = us.getUsersByNameAndAge("张三", 50);

//将@Cacheable的key参数改为key="#name"之后,下面的方法将可以执行。

User u2 = us.getAnotherUser("李四", 50);

System.out.println(u1==u2);

}

可以看到这回getAnotherUser()方法得到执行了,

1 正在执行getUsersByNameAndAge()..

2 正在执行getAnotherUser()..

3 false

我们也可以设置condition属性,例如,

@Service("userService")

@Cacheable(value="users", condition="#age<100")

public class UserServiceImpl implements UserService {

@Override

public User getUsersByNameAndAge(String name, int age) {

那么对于下面的代码来说,两个方法都不会被缓存,Spring每次都是执行真正的方法取结果,

public static void test2() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserService us = ctx.getBean("userService", UserService.class);

User u1 = us.getUsersByNameAndAge("张三", 500);

User u2 = us.getAnotherUser("李四", 500);

System.out.println(u1==u2);

}

执行结果,

正在执行getUsersByNameAndAge()..

正在执行getAnotherUser()..

false

方法级别的缓存

方法级别的缓存则只会对方法起作用了,不同的方法可以设置不用的缓存区,例如下面这样,

@Service("userService")

public class UserServiceImpl implements UserService {

@Cacheable("users1")

@Override

public User getUsersByNameAndAge(String name, int age) {

System.out.println("正在执行getUsersByNameAndAge()..");

return new User(name,age);

}

@Cacheable("users2")

@Override

public User getAnotherUser(String name, int age) {

System.out.println("正在执行getAnotherUser()..");

return new User(name,age);

}

}

使用下面的测试代码,

public static void test2() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserService us = ctx.getBean("userService", UserService.class);

//第一次执行方法,方法将会真正执行并缓存

User u1 = us.getUsersByNameAndAge("张三", 500);

//虽然下面方法传入相同参数,但是因为这两个方法在不同的缓存区,所以无法使用缓存数据

User u2 = us.getAnotherUser("张三", 500);

System.out.println(u1==u2);

//上面已经缓存过,这里不会真正执行,直接使用缓存

User u3 = us.getAnotherUser("张三", 500);

System.out.println(u3==u2);

}

执行结果,

正在执行getUsersByNameAndAge()..

正在执行getAnotherUser()..

false

true

使用@CacheEvict清除缓存

被@CacheEvict修饰的方法可以用来清除缓存,使用@CacheEvict可以指定如下属性。

allEntries, 是否清空整个缓存区

beforeInvocation: 是否在执行方法之前清除缓存。默认是方法执行成功之后才清除。

condiition以及key, 与@Cacheable中一样的含义。

下面示范简单用啊,

@Service("userService")

@Cacheable("users")

public class UserServiceImpl implements UserService {

@Override

public User getUsersByNameAndAge(String name, int age) {

System.out.println("正在执行getUsersByNameAndAge()..");

return new User(name,age);

}

@Override

public User getAnotherUser(String name, int age) {

System.out.println("正在执行getAnotherUser()..");

return new User(name,age);

}

//指定根据name,age参数清楚缓存

@CacheEvict(value="users")

public void evictUser(String name, int age) {

System.out.println("--正在清空"+name+","+age+"对应的缓存--");

}

//指定清除user缓存区所有缓存的数据

@CacheEvict(value="users", allEntries=true)

public void evictAll() {

System.out.println("--正在清空整个缓存--");

}

}

下面是测试类,

public static void test2() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserService us = ctx.getBean("userService", UserService.class);

//系统会缓存两个方法

User u1 = us.getUsersByNameAndAge("张三", 500);

User u2 = us.getAnotherUser("李四",400);

//调用evictUser()方法清除缓冲区指定的数据

us.evictUser("李四", 400);

//前面清除了 李四, 400 的缓存,下面的方法返回的数据将会再次被缓存

User u3 = us.getAnotherUser("李四", 400);

System.out.println(us == u3); //false

//前面已经缓存了 张三, 500的数据,下面方法不会重新执行,直接取缓存中的数据

User u4 = us.getAnotherUser("张三", 500);

System.out.println(u1==u4); //输出true

//清空整个缓存

us.evictAll();

//由于整个缓存都已经被清空,下面的代码都会被重新执行

User u5 = us.getAnotherUser("张三", 500);

User u6 = us.getAnotherUser("李四", 400);

System.out.println(u1==u5); //输出false

System.out.println(u3==u6); //输出false

}

执行结果,

正在执行getUsersByNameAndAge()..

正在执行getAnotherUser()..

--正在清空李四,400对应的缓存--

正在执行getAnotherUser()..

false

true

--正在清空整个缓存--

正在执行getAnotherUser()..

正在执行getAnotherUser()..

false

false

总结

以上就是本文关于Spring缓存机制实例代码的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

maxElementsInMemory="10000"

eternal="false"

overflowToDisk="true"

timeToIdleSeconds="300"

timeToLiveSeconds="600" />

上面的ehcache.xml配置了两个缓存区,Spring中的Bean将会缓存在这些缓存区中,一般的,Spring容器中有多少个Bean,就会在ehcache中定义多少个缓存区。

接着在Spring配置文件中配置缓存管理器如下,其中第一个Bean是一个工厂Bean,用来配置EhCache的CacheManager, 第二个Bean才是为Spring缓存配置的缓存管理器,所以将第一个Bean注入第二个Bean。

class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"

p:configLocation="classpath:ehcache.xml"

p:shared="false" />

class="org.springframework.cache.ehcache.EhCacheCacheManager"

p:cacheManager-ref="ehCacheManager" >

下面是一个完整的Spring配置,

xmlns:xsi="http://w3.org/2001/XMLSchema-instance"

xmlns:p="http://springframework.org/schema/p"

xmlns:cache="http://springframework.org/schema/cache"

xmlns:context="http://springframework.org/schema/context"

xsi:schemaLocation="http://springframework.org/schema/beans

http://springframework.org/schema/beans/spring-beans-4.0.xsd

http://springframework.org/schema/cache

http://springframework.org/schema/cache/spring-cache-4.0.xsd

http://springframework.org/schema/context

http://springframework.org/schema/context/spring-context-4.0.xsd">

base-package="com.service"/>

class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"

p:configLocation="classpath:ehcache.xml"

p:shared="false" />

class="org.springframework.cache.ehcache.EhCacheCacheManager"

p:cacheManager-ref="ehCacheManager" >

下面将以@Cacheable为例,演示Spring基于EhCache缓存的用法。 Cacheable用于修饰类或者方法,如果修饰类,则类中所有方法都会被缓存。

类级别的缓存

例如有如下Bean类,

@Service("userService")

@Cacheable(value="users")

public class UserServiceImpl implements UserService {

@Override

public User getUsersByNameAndAge(String name, int age) {

System.out.println("正在执行getUsersByNameAndAge()..");

return new User(name,age);

}

@Override

public User getAnotherUser(String name, int age) {

System.out.println("正在执行getAnotherUser()..");

return new User(name,age);

}

}

基于类的缓存,将会缓存类中的所有方法,缓存之后,程序调用该类实例的任何方法,只要传入的参数相同,Spring将不会真正执行该方法,而是直接根据传入的参数去查找缓存中的数据!

比如像下面这样使用缓存数据,

public static void test2() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserService us = ctx.getBean("userService", UserService.class);

User u1 = us.getUsersByNameAndAge("张三", 50);

//由于第二次调用userService方法时,使用了相同参数,那么真正的方法将不会执行,

//Spring将直接从缓存按参数查找数据

User u2 = us.getAnotherUser("张三", 50);

System.out.println(u1==u2);

}

输出结果,

正在执行getUsersByNameAndAge()..

true

可以看到,上面的getAnotherUser()并没有真正执行,因为传入的参数与之前的方法传入的参数相同,于是Spring直接从缓存区数据了。

上面的Bean类中的注解@Cacheable除了必选属性value之外,还有key, condition,, unless属性,后面三个都是用来设置Spring存储策略,对于基于类的缓存来说,Spring默认以方法传入的参数作为key去缓存中查找结果。

当然我们也可以修改key的策略,让Spring按照其他标准,比如按照第一个参数是否相同来作为key,在缓存中查找结果。

将上面的Bean类修改如下,

@Service("userService")

@Cacheable(value="users", key="#name")

public class UserServiceImpl implements UserService {

@Override

public User getUsersByNameAndAge(String name, int age) {

意味着我们传入相同的name,Spring就不会真正执行方法。只有name不同的时候,方法才会真正执行,例如下面,

public static void test2() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserService us = ctx.getBean("userService", UserService.class);

User u1 = us.getUsersByNameAndAge("张三", 50);

//将@Cacheable的key参数改为key="#name"之后,下面的方法将可以执行。

User u2 = us.getAnotherUser("李四", 50);

System.out.println(u1==u2);

}

可以看到这回getAnotherUser()方法得到执行了,

1 正在执行getUsersByNameAndAge()..

2 正在执行getAnotherUser()..

3 false

我们也可以设置condition属性,例如,

@Service("userService")

@Cacheable(value="users", condition="#age<100")

public class UserServiceImpl implements UserService {

@Override

public User getUsersByNameAndAge(String name, int age) {

那么对于下面的代码来说,两个方法都不会被缓存,Spring每次都是执行真正的方法取结果,

public static void test2() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserService us = ctx.getBean("userService", UserService.class);

User u1 = us.getUsersByNameAndAge("张三", 500);

User u2 = us.getAnotherUser("李四", 500);

System.out.println(u1==u2);

}

执行结果,

正在执行getUsersByNameAndAge()..

正在执行getAnotherUser()..

false

方法级别的缓存

方法级别的缓存则只会对方法起作用了,不同的方法可以设置不用的缓存区,例如下面这样,

@Service("userService")

public class UserServiceImpl implements UserService {

@Cacheable("users1")

@Override

public User getUsersByNameAndAge(String name, int age) {

System.out.println("正在执行getUsersByNameAndAge()..");

return new User(name,age);

}

@Cacheable("users2")

@Override

public User getAnotherUser(String name, int age) {

System.out.println("正在执行getAnotherUser()..");

return new User(name,age);

}

}

使用下面的测试代码,

public static void test2() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserService us = ctx.getBean("userService", UserService.class);

//第一次执行方法,方法将会真正执行并缓存

User u1 = us.getUsersByNameAndAge("张三", 500);

//虽然下面方法传入相同参数,但是因为这两个方法在不同的缓存区,所以无法使用缓存数据

User u2 = us.getAnotherUser("张三", 500);

System.out.println(u1==u2);

//上面已经缓存过,这里不会真正执行,直接使用缓存

User u3 = us.getAnotherUser("张三", 500);

System.out.println(u3==u2);

}

执行结果,

正在执行getUsersByNameAndAge()..

正在执行getAnotherUser()..

false

true

使用@CacheEvict清除缓存

被@CacheEvict修饰的方法可以用来清除缓存,使用@CacheEvict可以指定如下属性。

allEntries, 是否清空整个缓存区

beforeInvocation: 是否在执行方法之前清除缓存。默认是方法执行成功之后才清除。

condiition以及key, 与@Cacheable中一样的含义。

下面示范简单用啊,

@Service("userService")

@Cacheable("users")

public class UserServiceImpl implements UserService {

@Override

public User getUsersByNameAndAge(String name, int age) {

System.out.println("正在执行getUsersByNameAndAge()..");

return new User(name,age);

}

@Override

public User getAnotherUser(String name, int age) {

System.out.println("正在执行getAnotherUser()..");

return new User(name,age);

}

//指定根据name,age参数清楚缓存

@CacheEvict(value="users")

public void evictUser(String name, int age) {

System.out.println("--正在清空"+name+","+age+"对应的缓存--");

}

//指定清除user缓存区所有缓存的数据

@CacheEvict(value="users", allEntries=true)

public void evictAll() {

System.out.println("--正在清空整个缓存--");

}

}

下面是测试类,

public static void test2() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserService us = ctx.getBean("userService", UserService.class);

//系统会缓存两个方法

User u1 = us.getUsersByNameAndAge("张三", 500);

User u2 = us.getAnotherUser("李四",400);

//调用evictUser()方法清除缓冲区指定的数据

us.evictUser("李四", 400);

//前面清除了 李四, 400 的缓存,下面的方法返回的数据将会再次被缓存

User u3 = us.getAnotherUser("李四", 400);

System.out.println(us == u3); //false

//前面已经缓存了 张三, 500的数据,下面方法不会重新执行,直接取缓存中的数据

User u4 = us.getAnotherUser("张三", 500);

System.out.println(u1==u4); //输出true

//清空整个缓存

us.evictAll();

//由于整个缓存都已经被清空,下面的代码都会被重新执行

User u5 = us.getAnotherUser("张三", 500);

User u6 = us.getAnotherUser("李四", 400);

System.out.println(u1==u5); //输出false

System.out.println(u3==u6); //输出false

}

执行结果,

正在执行getUsersByNameAndAge()..

正在执行getAnotherUser()..

--正在清空李四,400对应的缓存--

正在执行getAnotherUser()..

false

true

--正在清空整个缓存--

正在执行getAnotherUser()..

正在执行getAnotherUser()..

false

false

总结

以上就是本文关于Spring缓存机制实例代码的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"

p:configLocation="classpath:ehcache.xml"

p:shared="false" />

class="org.springframework.cache.ehcache.EhCacheCacheManager"

p:cacheManager-ref="ehCacheManager" >

class="org.springframework.cache.ehcache.EhCacheCacheManager"

p:cacheManager-ref="ehCacheManager" >

下面是一个完整的Spring配置,

xmlns:xsi="http://w3.org/2001/XMLSchema-instance"

xmlns:p="http://springframework.org/schema/p"

xmlns:cache="http://springframework.org/schema/cache"

xmlns:context="http://springframework.org/schema/context"

xsi:schemaLocation="http://springframework.org/schema/beans

http://springframework.org/schema/beans/spring-beans-4.0.xsd

http://springframework.org/schema/cache

http://springframework.org/schema/cache/spring-cache-4.0.xsd

http://springframework.org/schema/context

http://springframework.org/schema/context/spring-context-4.0.xsd">

base-package="com.service"/>

class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"

p:configLocation="classpath:ehcache.xml"

p:shared="false" />

class="org.springframework.cache.ehcache.EhCacheCacheManager"

p:cacheManager-ref="ehCacheManager" >

xmlns:xsi="http://w3.org/2001/XMLSchema-instance"

xmlns:p="http://springframework.org/schema/p"

xmlns:cache="http://springframework.org/schema/cache"

xmlns:context="http://springframework.org/schema/context"

xsi:schemaLocation="http://springframework.org/schema/beans

http://springframework.org/schema/beans/spring-beans-4.0.xsd

http://springframework.org/schema/cache

http://springframework.org/schema/cache/spring-cache-4.0.xsd

http://springframework.org/schema/context

http://springframework.org/schema/context/spring-context-4.0.xsd">

base-package="com.service"/>

class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"

p:configLocation="classpath:ehcache.xml"

p:shared="false" />

class="org.springframework.cache.ehcache.EhCacheCacheManager"

p:cacheManager-ref="ehCacheManager" >

base-package="com.service"/>

class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"

p:configLocation="classpath:ehcache.xml"

p:shared="false" />

class="org.springframework.cache.ehcache.EhCacheCacheManager"

p:cacheManager-ref="ehCacheManager" >

class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"

p:configLocation="classpath:ehcache.xml"

p:shared="false" />

class="org.springframework.cache.ehcache.EhCacheCacheManager"

p:cacheManager-ref="ehCacheManager" >

class="org.springframework.cache.ehcache.EhCacheCacheManager"

p:cacheManager-ref="ehCacheManager" >

下面将以@Cacheable为例,演示Spring基于EhCache缓存的用法。 Cacheable用于修饰类或者方法,如果修饰类,则类中所有方法都会被缓存。

类级别的缓存

例如有如下Bean类,

@Service("userService")

@Cacheable(value="users")

public class UserServiceImpl implements UserService {

@Override

public User getUsersByNameAndAge(String name, int age) {

System.out.println("正在执行getUsersByNameAndAge()..");

return new User(name,age);

}

@Override

public User getAnotherUser(String name, int age) {

System.out.println("正在执行getAnotherUser()..");

return new User(name,age);

}

}

基于类的缓存,将会缓存类中的所有方法,缓存之后,程序调用该类实例的任何方法,只要传入的参数相同,Spring将不会真正执行该方法,而是直接根据传入的参数去查找缓存中的数据!

比如像下面这样使用缓存数据,

public static void test2() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserService us = ctx.getBean("userService", UserService.class);

User u1 = us.getUsersByNameAndAge("张三", 50);

//由于第二次调用userService方法时,使用了相同参数,那么真正的方法将不会执行,

//Spring将直接从缓存按参数查找数据

User u2 = us.getAnotherUser("张三", 50);

System.out.println(u1==u2);

}

输出结果,

正在执行getUsersByNameAndAge()..

true

可以看到,上面的getAnotherUser()并没有真正执行,因为传入的参数与之前的方法传入的参数相同,于是Spring直接从缓存区数据了。

上面的Bean类中的注解@Cacheable除了必选属性value之外,还有key, condition,, unless属性,后面三个都是用来设置Spring存储策略,对于基于类的缓存来说,Spring默认以方法传入的参数作为key去缓存中查找结果。

当然我们也可以修改key的策略,让Spring按照其他标准,比如按照第一个参数是否相同来作为key,在缓存中查找结果。

将上面的Bean类修改如下,

@Service("userService")

@Cacheable(value="users", key="#name")

public class UserServiceImpl implements UserService {

@Override

public User getUsersByNameAndAge(String name, int age) {

意味着我们传入相同的name,Spring就不会真正执行方法。只有name不同的时候,方法才会真正执行,例如下面,

public static void test2() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserService us = ctx.getBean("userService", UserService.class);

User u1 = us.getUsersByNameAndAge("张三", 50);

//将@Cacheable的key参数改为key="#name"之后,下面的方法将可以执行。

User u2 = us.getAnotherUser("李四", 50);

System.out.println(u1==u2);

}

可以看到这回getAnotherUser()方法得到执行了,

1 正在执行getUsersByNameAndAge()..

2 正在执行getAnotherUser()..

3 false

我们也可以设置condition属性,例如,

@Service("userService")

@Cacheable(value="users", condition="#age<100")

public class UserServiceImpl implements UserService {

@Override

public User getUsersByNameAndAge(String name, int age) {

那么对于下面的代码来说,两个方法都不会被缓存,Spring每次都是执行真正的方法取结果,

public static void test2() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserService us = ctx.getBean("userService", UserService.class);

User u1 = us.getUsersByNameAndAge("张三", 500);

User u2 = us.getAnotherUser("李四", 500);

System.out.println(u1==u2);

}

执行结果,

正在执行getUsersByNameAndAge()..

正在执行getAnotherUser()..

false

方法级别的缓存

方法级别的缓存则只会对方法起作用了,不同的方法可以设置不用的缓存区,例如下面这样,

@Service("userService")

public class UserServiceImpl implements UserService {

@Cacheable("users1")

@Override

public User getUsersByNameAndAge(String name, int age) {

System.out.println("正在执行getUsersByNameAndAge()..");

return new User(name,age);

}

@Cacheable("users2")

@Override

public User getAnotherUser(String name, int age) {

System.out.println("正在执行getAnotherUser()..");

return new User(name,age);

}

}

使用下面的测试代码,

public static void test2() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserService us = ctx.getBean("userService", UserService.class);

//第一次执行方法,方法将会真正执行并缓存

User u1 = us.getUsersByNameAndAge("张三", 500);

//虽然下面方法传入相同参数,但是因为这两个方法在不同的缓存区,所以无法使用缓存数据

User u2 = us.getAnotherUser("张三", 500);

System.out.println(u1==u2);

//上面已经缓存过,这里不会真正执行,直接使用缓存

User u3 = us.getAnotherUser("张三", 500);

System.out.println(u3==u2);

}

执行结果,

正在执行getUsersByNameAndAge()..

正在执行getAnotherUser()..

false

true

使用@CacheEvict清除缓存

被@CacheEvict修饰的方法可以用来清除缓存,使用@CacheEvict可以指定如下属性。

allEntries, 是否清空整个缓存区

beforeInvocation: 是否在执行方法之前清除缓存。默认是方法执行成功之后才清除。

condiition以及key, 与@Cacheable中一样的含义。

下面示范简单用啊,

@Service("userService")

@Cacheable("users")

public class UserServiceImpl implements UserService {

@Override

public User getUsersByNameAndAge(String name, int age) {

System.out.println("正在执行getUsersByNameAndAge()..");

return new User(name,age);

}

@Override

public User getAnotherUser(String name, int age) {

System.out.println("正在执行getAnotherUser()..");

return new User(name,age);

}

//指定根据name,age参数清楚缓存

@CacheEvict(value="users")

public void evictUser(String name, int age) {

System.out.println("--正在清空"+name+","+age+"对应的缓存--");

}

//指定清除user缓存区所有缓存的数据

@CacheEvict(value="users", allEntries=true)

public void evictAll() {

System.out.println("--正在清空整个缓存--");

}

}

下面是测试类,

public static void test2() {

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

UserService us = ctx.getBean("userService", UserService.class);

//系统会缓存两个方法

User u1 = us.getUsersByNameAndAge("张三", 500);

User u2 = us.getAnotherUser("李四",400);

//调用evictUser()方法清除缓冲区指定的数据

us.evictUser("李四", 400);

//前面清除了 李四, 400 的缓存,下面的方法返回的数据将会再次被缓存

User u3 = us.getAnotherUser("李四", 400);

System.out.println(us == u3); //false

//前面已经缓存了 张三, 500的数据,下面方法不会重新执行,直接取缓存中的数据

User u4 = us.getAnotherUser("张三", 500);

System.out.println(u1==u4); //输出true

//清空整个缓存

us.evictAll();

//由于整个缓存都已经被清空,下面的代码都会被重新执行

User u5 = us.getAnotherUser("张三", 500);

User u6 = us.getAnotherUser("李四", 400);

System.out.println(u1==u5); //输出false

System.out.println(u3==u6); //输出false

}

执行结果,

正在执行getUsersByNameAndAge()..

正在执行getAnotherUser()..

--正在清空李四,400对应的缓存--

正在执行getAnotherUser()..

false

true

--正在清空整个缓存--

正在执行getAnotherUser()..

正在执行getAnotherUser()..

false

false

总结

以上就是本文关于Spring缓存机制实例代码的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:VUE 使用中踩过的坑
下一篇:api接口管理是什么意思(api数据接口是什么意思)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~