Spring AOP的案例

jopen 10年前

        因为初衷只是为了给代码中加入一些日志,而我后来想到顺便加上一个对service层的方法执行时间的统计。对于这个,衍生出一个线程安全问题,统计时间意味着在Before需要有一个变量去接收起始时间,在After时获得之前的变量值进行计算并输出。这样一来之前的变量在并发情况下,后来的访问的起始时间将会覆盖这个变量值,想到ThreadLocal,泛型Long。由此解决线程安全问题。

        关于ThreadLocal,请自行google。

 

切面类

package com.eric.aop.aspect;    import java.lang.reflect.Method;  import java.text.MessageFormat;    import org.springframework.aop.AfterReturningAdvice;  import org.springframework.aop.MethodBeforeAdvice;  import org.springframework.aop.ThrowsAdvice;    public class MyAspect implements MethodBeforeAdvice, AfterReturningAdvice,    ThrowsAdvice {   private ThreadLocal<Long> tl=new ThreadLocal<Long>();      public void before(Method method, Object[] objArr, Object target)     throws Throwable {    // 获得当前时间,set到ThreadLocal中    tl.set(System.currentTimeMillis());   }      public void afterReturning(Object obj, Method method, Object[] objArr,     Object target) throws Throwable {    // 从ThreadLocal中get值并进行计算    long runTime=System.currentTimeMillis()-tl.get();    System.out.println(MessageFormat.format("{0}>>>本次耗时>>>{1}ms",       Thread.currentThread().getName(),runTime));   }   public void afterThrowing(Method method, Object[] objArr, Object target,     Exception ex) throws Throwable {    System.out.println("err>>>"+ex);   }  }

业务接口类

package com.eric.aop.service;    public interface VOService {          public void print();  }


业务实现类

package com.eric.aop.service.imp;    import org.springframework.context.annotation.Scope;  import org.springframework.stereotype.Service;    import com.eric.aop.service.VOService;    @Service("vOService")  @Scope("prototype")  public class VOServiceImpl implements VOService {     public void print() {    System.out.println("我是VO");    try {     Thread.sleep(new Random().nextInt(10000));     // Object obj=null;     // obj.toString();    } catch (InterruptedException e) {    }   }    }

Spring配置

<?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:context="http://www.springframework.org/schema/context"        xsi:schemaLocation="http://www.springframework.org/schema/beans           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd           http://www.springframework.org/schema/context           http://www.springframework.org/schema/context/spring-context-2.5.xsd        http://www.springframework.org/schema/tx        http://www.springframework.org/schema/tx/spring-tx-2.5.xsd        http://www.springframework.org/schema/aop        http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">            <context:annotation-config />        <!-- 扫描com.eric 下所有的包-->        <context:component-scan base-package="com.eric" />            <bean id="testAdvice" class="com.eric.aop.aspect.MyAspect" />        <aop:config>           <aop:advisor pointcut="execution(* com.eric.aop.*.*Service.*(..))"                advice-ref="testAdvice" />        </aop:config>    </beans>

测试类

package com.eric.aop.test;    import org.springframework.context.ApplicationContext;  import org.springframework.context.support.ClassPathXmlApplicationContext;  import com.eric.aop.service.VOService;    public class AopTest {   public static void main(String[] args) throws InterruptedException {    ApplicationContext ac = new ClassPathXmlApplicationContext(      "applicationContext.xml");    int t = 9;    for (int i = 0; i < t; i++) {     new Thread(new ThreadTest(ac)).start();    }   }  }  class ThreadTest implements Runnable {   private ApplicationContext ac;     public ThreadTest(ApplicationContext ac) {    this.ac = ac;   }   public void run() {    VOService vo = (VOService) ac.getBean("vOService");    vo.print();   }  }

 

输出结果

我是VO  我是VO  我是VO  我是VO  我是VO  我是VO  我是VO  我是VO  我是VO  Thread-7>>>本次耗时>>>292ms  Thread-2>>>本次耗时>>>1,387ms  Thread-5>>>本次耗时>>>1,707ms  Thread-1>>>本次耗时>>>2,686ms  Thread-9>>>本次耗时>>>4,874ms  Thread-3>>>本次耗时>>>5,173ms  Thread-6>>>本次耗时>>>6,033ms  Thread-8>>>本次耗时>>>9,379ms  Thread-4>>>本次耗时>>>9,740ms

来自:http://my.oschina.net/iseric/blog/290056