aop切面

aop在日常开发中最常见的两种使用场景是:1.记录日志,2.声明式事务处理。由于近年来springcloud的火热,springboot成为了首选的开发框架。相比spring,springboot最大的特点就是省略了大量的配置文件,让开发变得更加简单高效。
一、首先我们先谈谈aop在springboot中如何进行记录日志。代码如下

@Aspect
@Component
@Slf4j
public class MyAspect {

// 切点,定义横切的方法
@Pointcut("execution(public * com.zhb.aop.controller..*.*(..))")
public void pcut(){}

@Before("pcut()")
public void before(JoinPoint joinPoint){

    log.info("前置通知-------------");
    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = attributes.getRequest();
    log.info("url={}",request.getRequestURL());

// log.info(“url={}”,request.getMethod());
// log.info(“args={}”,joinPoint.getArgs());
}

@After("pcut()")
public void after(){

    log.info("后置通知------------");
}

@AfterReturning("pcut()")
public void afterRunning(){
    log.info("连接点执行完之后不出现异常的通知------------");
}

@AfterThrowing("pcut()")
public void exciption(){
    log.info("异常通知------------");
}

@Around("pcut()")
public Object around(ProceedingJoinPoint proceedingJoinPoint){
    log.info("环绕通知---------------qian");
    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = attributes.getRequest();
    String requestURI = request.getRequestURI();
    Enumeration<String> enumeration = request.getParameterNames();
    Map<String,String> parameterMap = new HashMap<>();
    while (enumeration.hasMoreElements()){
        String parameter = enumeration.nextElement();
        parameterMap.put(parameter,request.getParameter(parameter));
    }
    String args = JSON.toJSONString(parameterMap);
    log.info("请求接口地址:"+requestURI+",请求参数:"+args);
    Object proceed="";
    try {
        proceed = proceedingJoinPoint.proceed();
        log.info("环绕通知------------后");
    }catch (Throwable e){
        log.info("环绕异常通知");
    }
    log.info("环绕通知--------返回后通知");
    return proceed;
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
aop总共支持五种通知:前置通知@before,后置通知@after,返回通知@AfterReturning,异常通知@AfterThrowing,环绕通知@Around。我们可以看到环绕通知中基本可以处理其他的四种通知。注意:环绕通知的时候必须要执行proceed = proceedingJoinPoint.proceed();
记录日志是一方面,还可以利用aop实现拦截器的功能,例如:为某个应用提供接口,参数和响应内容都加密,我们可以在前置通知中进行参数解密,在后置通知中进行响应内容加密。二、接下来我们看一下声明式事务的处理。在springboot中如果用到事务只需要在service方法上注解@Transactional,这里需要注意一点
@Transactional 默认只捕获RuntimeException.class对Exception异常得需要 @Transactional(rollbackFor = {Exception.class}) 捕获回滚。 Exception和RuntimeException的区别可以看这个链接(https://blog.youkuaiyun.com/rotman173/article/details/38494491)。如果项目内和数据库交互特别多的时候,在每个service方法上注解是不是特别麻烦呢,这里就需要用到aop来实现事务,只需要配置切点,就可以实现事务,这样就方便多了,代码如下:

@Configuration
public class TransactionAspect {

// 事务失效时间
private static final int TX_METHOD_TIMEOUT=5000;
// 定义切点
private static final String pCut = "execution(public * com.zhb.aop.service..*.*(..))";

// 事务管理器
PlatformTransactionManager transactionManager;

/**
 * 配置了两种事务,一种是readOnly,另一种是required
 * @return
 */
@Bean
public TransactionInterceptor txAdvice(){

    NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
    RuleBasedTransactionAttribute readOnlyRule = new RuleBasedTransactionAttribute();
    readOnlyRule.setReadOnly(true);
    readOnlyRule.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);


    RuleBasedTransactionAttribute requiredRule = new RuleBasedTransactionAttribute();
    requiredRule.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
    requiredRule.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
    requiredRule.setTimeout(TX_METHOD_TIMEOUT);

    Map<String, TransactionAttribute> txMap = new HashMap<>();
    txMap.put("add*",requiredRule);

    txMap.put("find*",readOnlyRule);
    source.setNameMap(txMap);
    TransactionInterceptor advice = new TransactionInterceptor(transactionManager,source);
    return advice;
}

@Bean
public Advisor txAdvisor(){

    AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
    pointcut.setExpression(pCut);
    return new DefaultPointcutAdvisor(pointcut,txAdvice());
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值