通过AOP实现不改动代码对代码增强
aop即面向切面编程,它可以在不改动代码的情况下对其增强
首先创建一个需要被增强的方法
public void saveCustom() {
System.out.println("保存客户");
}
上述方法为模拟保存,而保存时为了防止出现部分成功部分失败的情况,所以需要对这个方法添加事务.
不使用AOP添加事务的流程
public void saveCustom() {
开启事务
System.out.println("保存客户");
提交事务
关闭
}
这种方法可以实现对sql语句添加事务的要求,但如果有很多个查询语句,每个都需要添加事务,这个工作量就比较大,而且还有很多重复代码,所以可以提取出重复的一部分封装成一个方法,然后调用,但这还是不够简便,如果使用AOP则可以实现除了业务核心方法外,不存在其他的方法
以下使用注解实现AOP
如果使用注解来创建AOP,则需要在Spring的配置文件中 开启AOP的注解支持
<!--扫描器-->
<context:component-scan base-package="com.gx"/>
<!--开启AOP注解支持-->
<aop:aspectj-autoproxy/>
然后创建一个类,用来存放增强代码
public class Logger {
}
此类需要进入容器并标注为切面,需要配置两个注解
//组件 logger
@Component("logger")
//配置了切面
@Aspect
//然后在此类中添加一个切入点表达式(即告诉spring 需要被增强的方法的位置)
//切入点表达式 最前面的 *表示匹配所有返回值类型 注 void也是一种返回值类型 com.gx.service.impl 表示被增强的方法放在哪个包中
//*(..) 表示匹配所有方法 方法可以是任意个参数
@Pointcut("execution(* com.gx.service.impl.*.*(..))")
private void pt1(){}
//接下来就是写增强代码 也就是通知 通知有五种 分别是前置通知,后置通知,异常通知,最终通知和环绕通知,一般前四种和最后一种选其一即可
前四种的写法
@Before("pt1()")//前置通知
public void beforeLog(){
System.out.println("前置通知");
}
@AfterReturning("pt1()")//后置通知
public void afterRuturningLog(){
System.out.println("后置通知");
}
@AfterThrowing("pt1()")//异常通知
public void throwingLog(){
System.out.println("异常通知");
}
@After("pt1()")//最终通知
public void afterLog(){
System.out.println("最终通知");
}
环绕通知的写法
@Around("pt1()")
public Object aroundLog(ProceedingJoinPoint pjp){
System.out.println("在环绕通知");
Object rtValue = null;
try {
System.out.println("前置通知");
rtValue = pjp.proceed(); //业务核心代码
System.out.println("后置通知");
} catch (Throwable throwable) {
System.out.println("异常通知");
throwable.printStackTrace();
}finally {
System.out.println("最终通知");
}
return rtValue;
}
输出结果 环绕通知输出结果和前四种差不多,所以只展示环绕通知