`
m635674608
  • 浏览: 5029083 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

spring Aop 之方法缓存

 
阅读更多

    因为公司人手原因,最近在为项目搭建架构,在异常,缓存,日志,方面都打算用Aop来做,在原来的项目中对在对异常,日志方面可能都是Log log=Logfactory.getLog();这样既麻烦,又紧耦合在一起。所以打算用Aop试试。下面是对一些缓存对象的Aop处理。主要是根据方法签名来做key值。

    定义一个注解

  

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MethodCache {
	int second() default 0; 
}

 

    定义一个业务处理类

 

public class Sev {
	@MethodCache(second=3)
	public Map getSort(int type,int parentid){
		System.out.println("no cache----");
		Map m =new HashMap();
		return m;
	}
	
	@MethodCache(second=3)
	public void getSort(){
		System.out.println("no cache----");
	}
}

 

   定义一个Aop

 

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Date;

import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class MethodCacheAspectJ {
	
	private Cache cache;
	
	/**
	 * 设置缓存名
	 */
	public void setCache(Cache cache) {
		this.cache = cache;
	} 
	
	@Pointcut("@annotation(com.zhang.shine.cache.MethodCache)")
	public void methodCachePointcut(){	
	}
	
	@Around("methodCachePointcut()")
	public Object methodCacheHold(ProceedingJoinPoint joinPoint) throws Throwable{
		System.out.println("aop start ");
		String targetName = joinPoint.getTarget().getClass().getName();
		String methodName = joinPoint.getSignature().getName();
		Object[] arguments = joinPoint.getArgs();
		Object result = null;
		String cacheKey = getCacheKey(targetName, methodName, arguments);
		System.out.println("key--"+cacheKey);
		Element element = cache.get(cacheKey);
		if (element == null) {
			try{
				result = joinPoint.proceed();
			}catch(Exception e){
				
			}
			if(result!=null){
				try{
					element = new Element(cacheKey, (Serializable) result);
					Class targetClass = Class.forName(targetName);
					Method[] method = targetClass.getMethods();
					int second = 0;
					for(Method m:method){
						if (m.getName().equals(methodName)) {
							Class[] tmpCs = m.getParameterTypes();
							if(tmpCs.length==arguments.length){
								MethodCache methodCache = m.getAnnotation(MethodCache.class);
								second = methodCache.second();
								break;
							}
						}
					}
					if(second>0){ // annotation没有设second值则使用ehcache.xml中自定义值
						element.setTimeToIdle(second);
						element.setTimeToLive(second);
					}
					cache.put(element);
				}catch(Exception e){
				}
			}
		}
		System.out.println("aop end ");
		return element.getValue();
	}

	 private String getCacheKey(String targetName, String methodName,
			Object[] arguments) {
		StringBuffer sb = new StringBuffer();
		sb.append(targetName).append(".").append(methodName);
		if ((arguments != null) && (arguments.length != 0)) {
			for (int i = 0; i < arguments.length; i++) {
				if (arguments[i] instanceof Date) {
					sb.append(".").append(
							DateUtil.datetoString((Date) arguments[i]));
				} else {
					sb.append(".").append(arguments[i]);
				}
			}
		}
		return sb.toString();
	}
}

 

    Spring配置文件

   

<bean id = "methodCacheAspectJ" class="com.zhang.shine.cache.MethodCacheAspectJ" >
		<property name="cache">
			<!-- <ref local="methodCache" /> -->
			<ref bean="methodCache"/>
		</property>
</bean>
<bean id="cacheManager"
		class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
		<property name="configLocation">
			<value>classpath:ehcache.xml</value>
		</property>
	</bean>
	
	<!-- 定义ehCache的工厂,并设置所使用的Cache name -->
	
	<bean id="methodCache"
		class="org.springframework.cache.ehcache.EhCacheFactoryBean">
		<property name="cacheManager">
			<ref local="cacheManager" />
		</property>
		<property name="cacheName">
			<value>DEFAULT_CACHE</value>
		</property>
	</bean>
<bean id="sev" class="com.zhang.shine.cache.Sev"></bean>

 

    ehcache.xml

  

 

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <diskStore path="/home/workspace/gzshine/trunk/ehcache"/>
	
	<defaultCache 
		maxElementsInMemory="50000" 
		eternal="false" 
		overflowToDisk="false" 
		timeToIdleSeconds="7200"
		timeToLiveSeconds="7200" 
		diskPersistent="false" 
		diskExpiryThreadIntervalSeconds="120"/>
		
	<cache name="DEFAULT_CACHE"
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="3600"
        timeToLiveSeconds="3600"
        overflowToDisk="true"
        />
</ehcache> 

 

   测试类

 

package test;



import net.sf.cglib.core.DebuggingClassWriter;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.zhang.shine.cache.CallImpl;
import com.zhang.shine.cache.MyImpl;
import com.zhang.shine.cache.Sev;
import sun.misc.*;
/**
 * 1.产生代理类$Proxy0类

执行了Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)

将产生$Proxy0类,它继承Proxy对象,并根据第二个参数,实现了被代理类的所有接口,自然就可以生成接口要实现的所有方法了(这时候会重写hashcode,toString和equals三个方法),但是还没有具体的实现体;

2.   将代理类$Proxy0类加载到JVM中

这时候是根据Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)它的第一个参数----就是被代理类的类加载器,把当前的代理类加载到JVM中

3.   创建代理类$Proxy0类的对象

调用的$Proxy0类的$Proxy0(InvocationHandler)构造函数,生成$Proxy0类的对象

参数就是Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)它的第三个参数

这个参数就是我们自己实现的InvocationHandler对象,我们知道InvocationHandler对象中组合加入了代理类代理的接口类的实现类;所以,$Proxy0对象调用所有要实现的接口的方法,都会调用InvocationHandler对象的invoke()方法实现;

4.   生成代理类的class byte

动态代理生成的都是二进制class字节码

 * @author zhang_zengmin
 *
 */
public class TestAOP {
	public static void main(String[] args) throws Exception{
   //cglib 代理对象class文件输出目录 如果是jdk动态代理就不输出
    /**
     * cglib头部信息
       public class Sev$$EnhancerByCGLIB$$bb4c2585 extends Sev
       implements SpringProxy, Advised, Factory
     */
	System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,  "c://class" );
	
	
		
      ApplicationContext ap =new ClassPathXmlApplicationContext("ApplicationContent.xml");
      Sev s = (Sev)ap.getBean("sev");
      //Sev s = new Sev();
      s.getSort(1, 2);
      //Thread.sleep(3010);
      s.getSort(1, 3);
     // s.getSort();
      System.out.println(s.getClass());
      
      MyImpl my=(MyImpl)ap.getBean("my");

       my.pao();
        //动态代理获取字节码  头部信息
       //public final class $Proxy0 extends Proxy implements Manager {

       /*byte[] proxyClassFile =	ProxyGenerator.generateProxyClass(
   		    proxyName, interfaces);*/
       
      /**
       * 接口默认Jdk代理
       */
     // ICall call = (ICall)ap.getBean("call");
      
     // call.cll();
       
     // Thread.sleep(60000);
     
     /* Enhancer enhancer = new Enhancer();//通过类Enhancer创建代理对象   
           enhancer.setSuperclass(Sev.class);//传入创建代理对象的类   
      
      
      ClassReader cr = new ClassReader(enhancer.getClass().getName());
      
      
       byte[] a = cr.b; 
       File f =new File("c://Sev.class");
       FileOutputStream  fout = new FileOutputStream(f);
       fout.write(a);
       fout.flush();
       fout.close();*/
       

     
     
	}
}

 

分享到:
评论

相关推荐

    SpringAOP结合ehCache实现简单缓存实例

    3. **创建缓存注解**:在Spring AOP中,我们可以创建一个自定义注解来标记需要缓存的方法。例如,创建一个名为`@Cacheable`的注解: ```java @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) ...

    Spring AOP+ehCache简单缓存系统解决方案

    在本篇【Spring AOP+ehCache简单缓存系统解决方案】中,我们将探讨如何利用Spring AOP(面向切面编程)和ehCache框架来构建一个高效、简单的缓存系统,以提升应用程序的性能。ehCache是一款流行的开源Java缓存库,它...

    Spring AOP实现Redis缓存数据库查询

    Spring AOP实现Redis缓存数据库查询 Spring AOP(Aspect-Oriented Programming,面向方面编程)是一种编程技术,可以将散落在各个对象之间的逻辑提取出来,封装成一个个独立的模块,并将这些模块组合起来,形成一...

    spring AOP实现查询缓存

    本代码通过使用spring aop+ehcache的技术,实现了方法级别的查询缓存,主要原理是 方法的完整路径+方法参数值,作为key,放入cache中,下次访问时先判断cache中是否有该key.

    Spring源码最难问题:当Spring AOP遇上循环依赖.docx

    Spring源码中最难的问题之一是循环依赖问题,当Spring AOP遇上循环依赖时,该如何解决? Spring通过三级缓存机制解决循环依赖的问题。 在Spring中,bean的实例化过程中,会先尝试从三级缓存中获取bean,这也是...

    Spring AOP面向方面编程原理:AOP概念

    Spring框架作为Java开发领域的领头羊之一,提供了强大的AOP支持。本文旨在深入探讨Spring AOP的核心概念及其原理。 #### 二、AOP基本概念 AOP是一种编程范式,其目的是提高模块化程度,特别是将那些对很多类都具有...

    spring aop 自定义缓存实现

    在Spring AOP(面向切面编程)中,自定义缓存是一种常见的优化技术,它可以显著提高应用程序的性能,减少对数据库或远程服务的重复访问。本实例将介绍如何利用Spring AOP来实现自定义缓存功能。 首先,理解Spring ...

    SpringAOP之探秘(动态代理、责任链模式、注解使用)

    Spring AOP可以结合缓存注解(如`@Cacheable`、`@CacheEvict`等)来实现高效的缓存操作,提升系统性能。 2. **第三章_proxy-demo.zip**:这个例子可能展示了如何创建和使用动态代理。你可能会看到如何通过Spring ...

    Spring AOP简单demo

    5. **缓存管理**:在方法调用前检查是否有缓存结果,避免重复计算。 6. **错误处理**:统一处理异常,提供友好的错误信息。 通过学习和实践Spring AOP,开发者可以更高效地组织代码,将关注点分离,提升代码的...

    Spring Aop使用实例

    - **缓存管理**:在方法调用前检查缓存,避免不必要的数据库查询。 ### 5. 示例项目`SpringAopPrj`分析 这个项目很可能是包含了一个Spring AOP的实战例子,可能包含了以下内容: - `LoggingAspect`类:定义切面,...

    springAop默认代理方式.zip

    8. **AOP应用场景**:Spring AOP广泛应用于日志记录、事务管理、权限控制、缓存管理等场景。通过切面可以将这些通用功能与业务逻辑解耦,提高代码的可维护性和可重用性。 总之,Spring AOP的默认代理方式是动态代理...

    使用spring aop对web 应用数据进行memcached缓存

    标题 "使用Spring AOP对Web应用数据进行Memcached缓存" 涉及到的关键技术是Spring AOP(面向切面编程)和Memcached,这是一种常见的高性能、分布式内存对象缓存系统。在Web应用程序中,使用缓存可以显著提高数据访问...

    第四章:Spring AOP API 设计模式1

    9. **享元模式(Flyweight)**:享元模式在Spring AOP中不太直接体现,但在Spring框架的其他部分,如缓存管理,可能会用到此模式来减少内存消耗,通过共享大量细粒度对象的内部状态来降低内存占用。 10. **代理模式...

    Spring AOP 1.0示例

    此外,Spring AOP还支持其他类型的通知,如`@After`(方法执行后)、`@AfterReturning`(正常返回后)、`@AfterThrowing`(抛出异常后)和`@Around`(环绕通知,完全控制方法的调用过程)。每种通知类型都有其特定的...

    使用SpringAop使用Oracle数据权限控制

    在实际项目中,可能还需要考虑其他因素,如缓存策略、性能优化以及与其他安全框架(如Spring Security)的协同工作等。总的来说,Spring AOP与Oracle的数据权限控制相结合,为大型企业应用提供了强大的安全保障。

    Spring AOP+ehCache简单缓存系统解决方案.doc

    Spring AOP 和 EhCache 结合使用提供了一个简单而有效的缓存解决方案,主要目的是优化系统性能,减少对数据库的频繁访问。下面将详细解释这个解决方案的关键组成部分。 首先,EhCache 是一个广泛使用的开源 Java ...

    spring Aop文档

    无论是对于初学者还是资深开发者来说,掌握Spring AOP都是非常有价值的技能之一。通过对Spring AOP的基本概念、配置方式以及源码层面的理解,我们可以更好地利用这一强大的工具来优化我们的应用程序。

    spring aop4.3.10

    8. **AOP应用场景**:Spring AOP广泛应用于事务管理、安全控制、缓存管理、日志记录等多个领域。例如,`@Transactional`注解可以方便地声明一个方法需要在数据库事务中执行。 9. **与其他Spring模块的集成**:...

Global site tag (gtag.js) - Google Analytics