encache整合spring应用实例

简介: 本文章摘编、转载需要注明来源 http://write.blog.csdn.net/postedit/8599512 缓存热点数据是提高访问效率的重要手段之一,下面我用encache...

本文章摘编、转载需要注明来源 http://write.blog.csdn.net/postedit/8599512 


缓存热点数据是提高访问效率的重要手段之一,下面我用encache演示下如何做service层的数据缓存


先写个方法拦截器,当然要先继承MethodInterceptor,encache的标识key我是将参数序列成json字符

 

可能强制部分会影响性能,建议判断null后再一次判断cache.get(key)是否为null,同步的第一人的操作已经执行完毕,那element里面就不为null,这样其他的并发用户就不需要

继续再执行put值的操作,这样做应该能比较好地降低synchronized带来的负面影响

/**
 * 缓存方法拦截器核心代码
 * 
 * @author shadow
 * @email 124010356@qq.com
 * @create 2012.04.28
 */
public class EhCacheMethodInterceptor implements MethodInterceptor,
		InitializingBean {

	 // private static final Logger log = Logger.getLogger(MethodCacheInterceptor.class);

	private Cache cache;

	public EhCacheMethodInterceptor() {
		super();
	}

	public void setCache(Cache cache) {
		this.cache = cache;
	}

	public void afterPropertiesSet() throws Exception {
		// /log.info(cache A cache is required. Use setCache(Cache) to provide one.");
	}

	public Object invoke(MethodInvocation invocation) throws Throwable {
		String targetName = invocation.getThis().getClass().getName();
		String methodName = invocation.getMethod().getName();
		Object[] arguments = invocation.getArguments();
		String cacheKey = getCacheKey(targetName, methodName, arguments);
		Element element = cache.get(cacheKey);

		// 缓存节点不存在的情况
		if (null == element) {
			synchronized (this) {
				// 这里判断是为了降低强制同步的负面影响,只需第一个操作该添加过程,后来者则跳过
				if (null == cache.get(cacheKey))
					element = putValueToCache(invocation, element, cacheKey);
			}
		}
		// 返回缓存值
		return element.getValue();

	}

	// 新增节点放到缓存区
	private Element putValueToCache(MethodInvocation invocation,
			Element element, String cacheKey) throws Throwable {
		Object result = invocation.proceed();
		element = new Element(cacheKey, (Serializable) result);
		cache.put(element);
		return element;
	}

	/**
	 * 
	 * 返回具体的方法(全路径+方法名+参数值)
	 * 
	 * @param targetName
	 *            全路径
	 * @param methodName
	 *            方法名称
	 * @param arguments
	 *            参数(转换成JSON格式方便比较)
	 * @return String
	 */
	private String getCacheKey(String targetName, String methodName,
			Object[] arguments) {
		StringBuffer buffer = new StringBuffer("");
		buffer.append(targetName).append(".").append(methodName);
		for (Object argument : arguments) {
			buffer.append(".")
					.append(BaseSupport.ContextUtil.getJSON(argument));
		}
		return buffer.toString();
	}

}


再做个同步数据的限制类,当我们执行remove等那些方法的时候会清空encache里面的相关缓存的方法数据,下次再访问的时候会重新在数据库里读取更新后的数据,到这里基本就可以了

package com.shadow.extras.cache;

import java.util.List;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;

/**
 * 缓存数据变动后让数据保持同步状态
 * 
 * @author shadow
 * @email 124010356@qq.com
 * @create 2012.04.28
 */
public class EhCacheMethodAfterAdvice {

	protected final Logger logger = Logger.getLogger(getClass());

	private CacheManager cacheManager;
	private Cache cacheName;

	/**
	 * 原始数据发生变更时保持强一致性(刪除緩存管理器里指定key的value)
	 * 
	 * @param joinPoint
	 */
	public void afterReturning(JoinPoint joinPoint) {
		// String methodName = joinPoint.getSignature().getName();// 得到执行的方法

		if (cacheManager != null && cacheName != null) {
			// 获取缓存堆
			Class<?> clazz = joinPoint.getTarget().getClass();
			List<?> list = cacheName.getKeys();
			for (int i = 0, len = list.size(); i < len; i++) {
				String key = String.valueOf(list.get(i));
				if (key.startsWith(clazz.getName()))
					cacheName.remove(key);
			}
		} else {
			if (cacheManager == null)
				logger.error("缓存管理器不存在!");
			if (cacheName == null)
				logger.error("缓存堆不存在!");
		}
	}

	public CacheManager getCacheManager() {
		return cacheManager;
	}

	public void setCacheManager(CacheManager cacheManager) {
		this.cacheManager = cacheManager;
	}

	public Cache getCacheName() {
		return cacheName;
	}

	public void setCacheName(Cache cacheName) {
		this.cacheName = cacheName;
	}

}



然后是在xml里配置需要拦截的方法

<?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:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:ehcache="http://www.springframework.org/schema/ehcache"
	xsi:schemaLocation="
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
     http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
     http://www.springframework.org/schema/ehcache  http://www.springframework.org/schema/cache/springmodules-ehcache.xsd">

	<!-- 配置缓存管理器 -->
	<bean id="defaultCacheManager"
		class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
		<property name="configLocation">
			<value>classpath:ehcache.xml</value>
		</property>
	</bean>

	<!-- 配置一个简单的缓存工厂bean对象 -->
	<bean id="defaultCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
		<property name="cacheManager">
			<ref local="defaultCacheManager" />
		</property>
		<!-- 使用缓存 关联ehcache.xml中的缓存配置 -->
		<property name="cacheName" value="defaultCache" />
	</bean>

	<!-- 配置一个简单的缓存工厂bean对象 -->
	<bean id="commonCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
		<property name="cacheManager">
			<ref local="defaultCacheManager" />
		</property>
		<!-- 使用缓存 关联ehcache.xml中的缓存配置 -->
		<property name="cacheName" value="commonCache" />
	</bean>

	<!-- 配置一个缓存拦截器对象,处理具体的缓存业务 -->
	<bean id="ehCacheMethodInterceptor" class="com.shadow.extras.cache.EhCacheMethodInterceptor">
		<property name="cache" ref="defaultCache" />
	</bean>

	<!-- 参与缓存的切入点对象 (切入点对象,确定何时何地调用拦截器) -->
	<bean id="methodCachePointCut"
		class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
		<!-- 配置缓存切面 -->
		<property name="advice" ref="ehCacheMethodInterceptor" />
		<!--
			配置哪些方法参与缓存策略 .表示符合任何单一字元 ### +表示符合前一个字元一次或多次 ### *表示符合前一个字元零次或多次 ###
			\Escape任何Regular expression使用到的符号
		-->
		<!-- .*表示前面的前缀(包括包名) 表示print方法-->
		<property name="patterns">
			<list>
				<value>
					com.xshadow.mvc.service\..*Service.*\.find.*
				</value>
			</list>
		</property>
	</bean>

	<!-- 配置一个缓存拦截器对象,处理具体的同步缓存业务 -->
	<bean id="ehCacheMethodAfterAdvice" class="com.shadow.extras.cache.EhCacheMethodAfterAdvice">
		<property name="cacheManager" ref="defaultCacheManager" />
		<property name="cacheName" ref="defaultCache" />
	</bean>
	<aop:config>
		<aop:aspect id="methodCachePointCutAdviceAspect" ref="ehCacheMethodAfterAdvice">
			<aop:after method="afterReturning"
				pointcut="execution(* com.shadow.mvc.service.*Service.modify*(..))" />
			<aop:after method="afterReturning"
				pointcut="execution(* com.shadow.mvc.service.*Service.save*(..))" />
			<aop:after method="afterReturning"
				pointcut="execution(* com.shadow.mvc.service.*Service.remove*(..))" />
		</aop:aspect>
	</aop:config>

</beans>


以后我们配置需要缓存的地方就直接在文件里配置就可以了,至于分布式的缓存应用有空再写

目录
相关文章
|
3月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
208 1
|
3月前
|
Java Maven Docker
gitlab-ci 集成 k3s 部署spring boot 应用
gitlab-ci 集成 k3s 部署spring boot 应用
|
16天前
|
人工智能 前端开发 Java
Spring AI Alibaba + 通义千问,开发AI应用如此简单!!!
本文介绍了如何使用Spring AI Alibaba开发一个简单的AI对话应用。通过引入`spring-ai-alibaba-starter`依赖和配置API密钥,结合Spring Boot项目,只需几行代码即可实现与AI模型的交互。具体步骤包括创建Spring Boot项目、编写Controller处理对话请求以及前端页面展示对话内容。此外,文章还介绍了如何通过添加对话记忆功能,使AI能够理解上下文并进行连贯对话。最后,总结了Spring AI为Java开发者带来的便利,简化了AI应用的开发流程。
241 0
|
4月前
|
安全 Java 网络安全
当网络安全成为数字生活的守护者:Spring Security,为您的应用筑起坚不可摧的防线
【9月更文挑战第2天】在数字化时代,网络安全至关重要。本文通过在线银行应用案例,详细介绍了Spring Security这一Java核心安全框架的核心功能及其配置方法。从身份验证、授权控制到防御常见攻击,Spring Security提供了全面的解决方案,确保应用安全。通过示例代码展示了如何配置`WebSecurityConfigurerAdapter`及`HttpSecurity`,帮助开发者有效保护应用免受安全威胁。
77 4
|
2月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
137 62
|
1月前
|
XML Java 数据格式
Spring Core核心类库的功能与应用实践分析
【12月更文挑战第1天】大家好,今天我们来聊聊Spring Core这个强大的核心类库。Spring Core作为Spring框架的基础,提供了控制反转(IOC)和依赖注入(DI)等核心功能,以及企业级功能,如JNDI和定时任务等。通过本文,我们将从概述、功能点、背景、业务点、底层原理等多个方面深入剖析Spring Core,并通过多个Java示例展示其应用实践,同时指出对应实践的优缺点。
57 14
|
2月前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
257 12
基于开源框架Spring AI Alibaba快速构建Java应用
|
1月前
|
XML 前端开发 安全
Spring MVC:深入理解与应用实践
Spring MVC是Spring框架提供的一个用于构建Web应用程序的Model-View-Controller(MVC)实现。它通过分离业务逻辑、数据、显示来组织代码,使得Web应用程序的开发变得更加简洁和高效。本文将从概述、功能点、背景、业务点、底层原理等多个方面深入剖析Spring MVC,并通过多个Java示例展示其应用实践,同时指出对应实践的优缺点。
81 2
|
2月前
|
JSON 安全 算法
Spring Boot 应用如何实现 JWT 认证?
Spring Boot 应用如何实现 JWT 认证?
88 8
|
2月前
|
消息中间件 Java Kafka
Spring Boot 与 Apache Kafka 集成详解:构建高效消息驱动应用
Spring Boot 与 Apache Kafka 集成详解:构建高效消息驱动应用
61 1
下一篇
开通oss服务