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>


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

目录
相关文章
|
5月前
|
监控 Java API
Spring Boot 3.2 结合 Spring Cloud 微服务架构实操指南 现代分布式应用系统构建实战教程
Spring Boot 3.2 + Spring Cloud 2023.0 微服务架构实践摘要 本文基于Spring Boot 3.2.5和Spring Cloud 2023.0.1最新稳定版本,演示现代微服务架构的构建过程。主要内容包括: 技术栈选择:采用Spring Cloud Netflix Eureka 4.1.0作为服务注册中心,Resilience4j 2.1.0替代Hystrix实现熔断机制,配合OpenFeign和Gateway等组件。 核心实操步骤: 搭建Eureka注册中心服务 构建商品
1001 3
|
4月前
|
SQL Java 数据库连接
Spring Data JPA 技术深度解析与应用指南
本文档全面介绍 Spring Data JPA 的核心概念、技术原理和实际应用。作为 Spring 生态系统中数据访问层的关键组件,Spring Data JPA 极大简化了 Java 持久层开发。本文将深入探讨其架构设计、核心接口、查询派生机制、事务管理以及与 Spring 框架的集成方式,并通过实际示例展示如何高效地使用这一技术。本文档约1500字,适合有一定 Spring 和 JPA 基础的开发者阅读。
522 0
|
11月前
|
人工智能 Java API
Java也能快速搭建AI应用?一文带你玩转Spring AI可落地性
Java语言凭借其成熟的生态与解决方案,特别是通过 Spring AI 框架,正迅速成为 AI 应用开发的新选择。本文将探讨如何利用 Spring AI Alibaba 构建在线聊天 AI 应用,并实现对其性能的全面可观测性。
2763 102
|
3月前
|
消息中间件 缓存 Java
Spring框架优化:提高Java应用的性能与适应性
以上方法均旨在综合考虑Java Spring 应该程序设计原则, 数据库交互, 编码实践和系统架构布局等多角度因素, 旨在达到高效稳定运转目标同时也易于未来扩展.
187 8
|
5月前
|
Java 应用服务中间件 开发者
Spring Boot 技术详解与应用实践
本文档旨在全面介绍 Spring Boot 这一广泛应用于现代企业级应用开发的框架。内容将涵盖 Spring Boot 的核心概念、核心特性、项目自动生成与结构解析、基础功能实现(如 RESTful API、数据访问)、配置管理以及最终的构建与部署。通过本文档,读者将能够理解 Spring Boot 如何简化 Spring 应用的初始搭建和开发过程,并掌握其基本使用方法。
452 2
|
5月前
|
人工智能 监控 安全
如何快速上手【Spring AOP】?核心应用实战(上篇)
哈喽大家好吖~欢迎来到Spring AOP系列教程的上篇 - 应用篇。在本篇,我们将专注于Spring AOP的实际应用,通过具体的代码示例和场景分析,帮助大家掌握AOP的使用方法和技巧。而在后续的下篇中,我们将深入探讨Spring AOP的实现原理和底层机制。 AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的核心特性之一,它能够帮助我们解决横切关注点(如日志记录、性能统计、安全控制、事务管理等)的问题,提高代码的模块化程度和复用性。
|
5月前
|
安全 算法 Java
在Spring Boot中应用Jasypt以加密配置信息。
通过以上步骤,可以在Spring Boot应用中有效地利用Jasypt对配置信息进行加密,这样即使配置文件被泄露,其中的敏感信息也不会直接暴露给攻击者。这是一种在不牺牲操作复杂度的情况下提升应用安全性的简便方法。
1167 10
|
6月前
|
NoSQL Java Redis
Redis基本数据类型及Spring Data Redis应用
Redis 是开源高性能键值对数据库,支持 String、Hash、List、Set、Sorted Set 等数据结构,适用于缓存、消息队列、排行榜等场景。具备高性能、原子操作及丰富功能,是分布式系统核心组件。
632 2
|
6月前
|
安全 Java Nacos
0代码改动实现Spring应用数据库帐密自动轮转
Nacos作为国内被广泛使用的配置中心,已经成为应用侧的基础设施产品,近年来安全问题被更多关注,这是中国国内软件行业逐渐迈向成熟的标志,也是必经之路,Nacos提供配置加密存储-运行时轮转的核心安全能力,将在应用安全领域承担更多职责。
|
6月前
|
Java Linux 网络安全
Linux云端服务器上部署Spring Boot应用的教程。
此流程涉及Linux命令行操作、系统服务管理及网络安全知识,需要管理员权限以进行配置和服务管理。务必在一个测试环境中验证所有步骤,确保一切配置正确无误后,再将应用部署到生产环境中。也可以使用如Ansible、Chef等配置管理工具来自动化部署过程,提升效率和可靠性。
693 13

热门文章

最新文章