思路
1.自定义注解
2.AOP类 拦截获取目标对象的方法及其是否存在注解
一。实现一个切面
1.自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExtTransaction {
}
2.AOP切面类
@Aspect
@Component
public class AOPTransaction {
@Autowired
TransactionUtils transactionUtils;
@Pointcut("execution(* com.aop.web.service.*.*(..))")
private void pointCut(){
};
@Around("com.aop.DIY.AOPTransaction.pointCut()") --上面有预先定义一个切点
@Around("execution(* javax.sql.DataSource.getConnection(..))") --直接指到要切面的具体方法
@Around("execution(* com.aop.web.service.*.*(..))") --直接指到包下
@Around("@annotation(com.lhc.annotation.GlobalTransaction )") --直接指到注解
public Object invoke(ProceedingJoinPoint pjp) throws Throwable {
//1.获取到目标对象的方法
//2.获取该方法上是否加上注解
//3.如果存在事务,开启事务
//4.调用目标对象方法
//5.判断该方法是否存在注解
//6.如果存在注解提交事务
System.out.println("AOP类进入拦截");
Object proceed = null;
TransactionStatus transactionStatus = null;
//1.百度SpringAOP获取目标对象的方法
Signature signature = pjp.getSignature();
MethodSignature methodSignature = (MethodSignature)signature;
Method targetMethod = methodSignature.getMethod();
//2.判断方法是否存在注解
ExtTransaction extTransaction = targetMethod.getDeclaredAnnotation(ExtTransaction.class);
if(extTransaction != null){
//3.如果存在注解,开启事务
transactionStatus = transactionUtils.begin();
}
//4.调用目标对象方法
proceed = pjp.proceed();
//5.判断该方法是否存在注解
if(extTransaction != null){
//6.如果存在注解,提交事务
transactionUtils.commit(transactionStatus);
}
return proceed;
}
}
切面类另外一种写法:写注解的位置,前缀是@annotation
上面写要拦截的类的位置,前缀是execution
@Aspect
@Component
public class GlobalTransactionAspect {
@Around("@annotation(com.lhc.annotation.GlobalTransaction )")
public Object invoke(ProceedingJoinPoint pjp) throws Throwable {
MethodSignature methodSignature = (MethodSignature)pjp.getSignature();
Method method = methodSignature.getMethod(); //拿到切的方法
GlobalTransaction annotation = method.getAnnotation(GlobalTransaction.class); //方法上的注解
annotation.isStart() //注解上的值
}
3.serviceImpl(即目标对象)方法上加注解
@Override
@ExtTransaction
public int insertRoleMenu() {
wholeDepartmentMapper.insertRoleMenu();
int j = 1/0;
return j;
}
二。设置切面类的优先级(假如有两个切面类)
实现 org.springframework.core.Ordered 接口,重写getOrder方法(返回的整形越大越优先)
@Aspect
@Component
public class GlobalTransactionAspect implements Ordered {
@Around("@annotation(com.lhc.txtransaction.annotation.GlobalTransaction )")
public Object invoke(ProceedingJoinPoint pjp) throws Throwable {
pjp.proceed();
}
@Override
public int getOrder() {
return 100000;
}
}
三。切面类拿到目标对象的方法,方法上的注解,注解值
public class GlobalTransactionAspect implements Ordered {
@Around("@annotation(com.lhc.txtransaction.annotation.GlobalTransaction )")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("进入GlobalTransactionAspect切面类");
MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
Method method = methodSignature.getMethod();
GlobalTransaction annotation = method.getAnnotation(GlobalTransaction.class);
annotation.isStart() //GlobalTransaction这个注解的值
}
}