执行时间获取:记录开始时间和结束时间,取差值。
这里使用环绕通知来实现。
环境准备:
项目文件结构:
业务层接口和实现类:
数据层:
采用mybatis注解开发,这里没有实现类,直接在接口方法里面实现映射。
domain层:
实现了数据库里面每一个属性的setter和getter方法以及一个tostring方法。
jdbc.properties文件下
SpringConfig配置类里面加载了 properties文件和jdbc以及mybatis的配置
Jdbc配置文件下:
使用一个Druid作为数据源
Mybayis配置文件下
加载了两个bean一个是SqlSessionFactory的bean,还有一个映射扫描的bean。
测试代码:
在test目录下整合了一个JUnit的测试类,并有两个查询的方法测试
AOP层:
现在SpringConfig配置类上添加一个发现Aspet的注解
再创建一个通知类,在里面定义一个切入点包含了业务层的所有操作,然后使用环绕通知的方式测试业务层接口执行万次的效率。
正常输出
现在的运行方法无法得知测试的是哪一个接口的哪一个实现类,为此需要获取是哪一个连接点的信息,用到了上面环绕方法中的属性参数 ProceedingJoinPoint,这个就是执行的连接点。
现在使用一个它下面的一个方法getSignature(),获取一次执行的签名信息,里面封装了一次执行的过程。Signature下的get方法就可以获取到很多信息
输出得到了一次执行里面的类型和方法名
AOP通知获取数据
- 获取原始操作的参数
- 获取原始操作的返回值
- 获取原始操作的异常
环境准备二:
Dao层的借口实现类,模拟根据id查询姓名
测试代码里面:
在前置通知里面获取参数
使用一个JoinPoint,用它下面的getArgs方法获取原始方法的参数
@Before("pt()")
public void before(JoinPoint jp){
Object[] args= jp.getArgs();
System.out.println(Arrays.toString(args));
System.out.println("before advice...");
}
输出为一个参数构成的数组,有多个参数就有多个不同类型的数据
在后置通知里面获取参数
和在前置通知获取参数一模一样
@After("pt()")
public void after(JoinPoint jp){
Object[] args= jp.getArgs();
System.out.println(Arrays.toString(args));
System.out.println("after advice...");
}
在环绕通知里面获取参数和返回值和异常
和上面类似,只是从JoinPoint改成了ProceedingJoinPoint,另外,这里面的args可以修改。但是数量和类型必须对应相同,这就是数据劫持?
@Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Object[] args=pjp.getArgs();
System.out.println(Arrays.toString(args));
args[0]=150;
Object ret= pjp.proceed(args);
return ret;
}
输出如图,原本在环绕通知里面刚获取到时是100,经过修改返回了一个150.
异常获取
使用catch环绕,其中的Throwable属性的参数就是异常
@Around("pt()")
public Object around(ProceedingJoinPoint pjp) {
Object[] args=pjp.getArgs();
System.out.println(Arrays.toString(args));
args[0]=150;
Object ret= null;
try {
ret = pjp.proceed(args);
} catch (Throwable e) {
throw new RuntimeException(e);
}
return ret;
}
在返回后通知里面获取返回值
解释为如果过原始方法又返回值,就把它装到原始变量叫ret的形参当中
@AfterReturning(value="pt()",returning = "ret")
public void afterReturning(Object ret){
System.out.println("afterReturning advice..."+ret);
}
正常输出
如果参数列存在两个参数,必须是JoinPoint在前面
@AfterReturning(value="pt()",returning = "ret")
public void afterReturning(JoinPoint jp,Object ret){
System.out.println("afterReturning advice..."+ret);
}
异常后通知获取异常
和上面返回后通知获取返回值类型
@AfterThrowing(value="pt()",throwing = "t")
public void afterThrowing(Throwable t){
System.out.println("afterThrowing advice..."+t);
}
在原始方法中出现一个异常
@Repository
public class BookDaoImpl implements BookDao {
public String findName(int id){
System.out.println("id:"+id);
if(true) throw new NullPointerException();
return "itcast";
}
}
输出如下
AOP总结