读书人

spring Aop 之步骤缓存

发布时间: 2012-12-28 10:29:04 作者: rapoo

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)@Documentedpublic @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;@Aspectpublic 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" ><property name="cache"><!-- <ref local="methodCache" /> --><ref bean="methodCache"/></property></bean><bean id="cacheManager"/></property><property name="cacheName"><value>DEFAULT_CACHE</value></property></bean><bean id="sev" name="code"><?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();*/                 }}

?

读书人网 >编程

热点推荐