AOP计算方法运行所需时间
一,前言
利用SpringAOP切面完成对java方法的运行时间计算
二,准备
创建JavaWeb项目,配置Spring,创建方法类,测试类,切面类
三,代码实现
1.配置xml文件
<!-- 定义目标对象 --> <bean id="stuimpl" class="com.stu.impl.StuImpl"></bean> <!-- 定义切面对象 --> <bean id="log" class="com.stu.Log"></bean> <!-- 切面配置 --> <aop:config> <!-- 切入点表达式:execution:具体到方法,within:具体到类,类中的所有方法,*:任意字符 ..:多层 execution(public void com.aaa.aop3.BookImpl.add(int)) execution(* * com..*.select*(..)) within(com.aaa.aop3.BookImpl):com.aaa.aop3.BookImpl下的所有方法 within(com.aaa.aop3.*):com.aaa.aop3包下所有类中所有方法 --> <!-- 定义一个可以被多个切面共享的切入点 --> <!-- <aop:pointcut expression="within(com.aaa.aop3.BookImpl)" id="points"/> --> <aop:pointcut expression="execution(* com.stu.impl.StuImpl.*(..))" id="points"/> <!-- 将id=log的对象作为切面使用 --> <aop:aspect ref="log"> <!-- method:方法 pointcut-ref:切入点 同时配置后置/异常/最终通知时:按照配置的先后顺序执行 -->
<!-- before:前置通知,总是在连接点调用前执行 --> <!-- <aop:before method="start" pointcut-ref="points"/> --> <!-- 后置通知:在方法正常执行完成之后调用 --> <!-- <aop:after-returning method="afterReturning" pointcut-ref="points"/> --> <!-- 异常通知:在方法异常执行之后调用 --> <!-- <aop:after-throwing method="afterThrowing" pointcut-ref="points" throwing="e"/> --> <!-- 最终通知:在方法执行完成之后调用 --> <!-- <aop:after method="after" pointcut-ref="points"/> --> <!-- 环绕通知:围绕方法的执行前后执行 --> <aop:around method="around" pointcut="execution(* com.stu.impl.StuImpl.*(..))"/> </aop:aspect> </aop:config>
2.Log类
package com.stu;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
public class Log {
//定义方法开始时间和结束时间
long startTime;
long afterTime;
public void start() {
//获取系统当前时间的毫秒数
startTime = System.currentTimeMillis();
System.out.println("前置通知before");
}
// JoinPoint:连接点对象
public void after(JoinPoint jp) {
System.out.println("最终通知after");
afterTime = System.currentTimeMillis();
Signature signature = jp.getSignature();
System.out.println(signature.getDeclaringTypeName()+"."+signature.getName()+"方法执行了"+(afterTime-startTime)+"ms");
}
public void afterReturning() {
System.out.println("后置通知afterReturning");
}
public void afterThrowing(JoinPoint jp,Exception e) throws Exception {
System.out.println("异常通知afterThrowing");
System.out.println("发生异常,异常的原因是" + e.getMessage());
}
/**
* ProceedingJoinPoint:正在执行的连接点,只能写在环绕通知中
*
* @return返回值表示的连接点的返回值
*/
public Object around(ProceedingJoinPoint pjp) {
Object obj = null;
System.out.println("环绕通知around");
try {
System.out.println("环绕前置通知");
startTime = System.currentTimeMillis();
// proceed():执行连接点,返回连接点的返回值
// 获取正在执行的连接点对象所在的类,打印结果:class org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint
Class<? extends ProceedingJoinPoint> class1 = pjp.getClass();
//System.out.println("class:" + class1);
// 当前执行的连接点,打印结果:int com.stu.impl.StuImpl.update(int,int)
Signature signature = pjp.getSignature();
//System.out.println("signature:" + signature);
// 连接点的方法名,打印结果:update
String name = signature.getName();
//System.out.println("name:" + name);
// 连接点所在的类,打印结果:class com.stu.impl.StuImpl
Class declaringType = signature.getDeclaringType();
//System.out.println("declaringType:" + declaringType);
// 连接点所在的类名全路径,打印结果:com.stu.impl.StuImpl
String declaringTypeName = signature.getDeclaringTypeName();
//System.out.println("declaringTypeName:" + declaringTypeName);
// 调用连接点的目标对象,打印结果:com.stu.impl.StuImpl@6e4784bc
Object target = pjp.getTarget();
//System.out.println("target:" + target);
// 连接点传递的参数列表
Object[] args = pjp.getArgs();
System.out.println("args.length:" + args.length);
for (Object o : args) {
System.out.println("arg:"+o);
}
obj = pjp.proceed();
System.out.println("环绕后置通知");
} catch (Throwable e) {
System.out.println("环绕异常通知");
Signature signature = pjp.getSignature();
System.out.println(signature.getDeclaringTypeName()+"."+signature.getName()+"方法时发生异常,异常的原因是" + e.getMessage());
} finally {
System.out.println("环绕最终通知");
afterTime = System.currentTimeMillis();
Signature signature = pjp.getSignature();
System.out.println(signature.getDeclaringTypeName()+"."+signature.getName()+"方法执行了"+(afterTime-startTime)+"ms");
}
return obj;
}
}
3.测试类
package com.stu;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.stu.impl.StuImpl;
public class StuTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
StuImpl stuimpl = context.getBean(StuImpl.class);
Object object = stuimpl.test(1, 2);
System.out.println("object的值"+o);
}
}
4.打印结果:使用环绕通知,异常后返回值0,使用Object接受返回值并输出
环绕通知around
环绕前置通知
args.length:2
arg:1
arg:2
test方法
环绕后置通知
环绕最终通知
com.stu.impl.StuImpl.test方法执行了16ms
object的值1

浙公网安备 33010602011771号