springboot利⽤aop记录⽇志和处理声明式事务
aop在⽇常开发中最常见的两种使⽤场景是:1.记录⽇志,2.声明式事务处理。由于近年来springcloud的⽕热,springboot成为了⾸选的开发框架。相⽐spring,springboot最⼤的特点就是省略了⼤量的配置⽂件,让开发变得更加简单⾼效。
⼀、⾸先我们先谈谈aop在springboot中如何进⾏记录⽇志。代码如下
@Aspect
@Component
@Slf4j
public class MyAspect {
// 切点,定义横切的⽅法
@Pointcut("execution(public * com.ller..*.*(..))")
public void pcut(){}
@Before("pcut()")
public void before(JoinPoint joinPoint){
log.info("前置通知-------------");
ServletRequestAttributes attributes =(ServletRequestAttributes) RequestAttributes(); HttpServletRequest request = Request();
log.info("url={}",RequestURL());
// log.info("url={}",Method());
// log.info("args={}",Args());
}
@After("pcut()")
public void after(){
log.info("后置通知------------");
}
@AfterReturning("pcut()")
public void afterRunning(){
log.info("连接点执⾏完之后不出现异常的通知------------");
}
@AfterThrowing("pcut()")
public void exciption(){
log.info("异常通知------------");
}
@Around("pcut()")spring aop应用场景
public Object around(ProceedingJoinPoint proceedingJoinPoint){
log.info("环绕通知---------------qian");
ServletRequestAttributes attributes =(ServletRequestAttributes) RequestAttributes(); HttpServletRequest request = Request();
String requestURI = RequestURI();
Enumeration<String> enumeration = ParameterNames();
Map<String,String> parameterMap =new HashMap<>();
while(enumeration.hasMoreElements()){
String parameter = Element();
parameterMap.put(Parameter(parameter));
}
String args = JSONString(parameterMap);
log.info("请求接⼝地址:"+requestURI+",请求参数:"+args);
Object proceed="";
try{
proceed = proceedingJoinPoint.proceed();
log.info("环绕通知------------后");
}catch(Throwable e){
log.info("环绕异常通知");
}
log.info("环绕通知--------返回后通知");
return proceed;
}
}
aop总共⽀持五种通知:前置通知@before,后置通知@after,返回通知@AfterReturning,异常通知@AfterThrowing,环绕通知
@Around。我们可以看到环绕通知中基本可以处理其他的四种通知。注意:环绕通知的时候必须要执⾏proceed = proceedingJoinPoint.proceed();
记录⽇志是⼀⽅⾯,还可以利⽤aop实现的功能,例如:为某个应⽤提供接⼝,参数和响应内容都加密,我们可以在前置通知中进⾏参数解密,在后置通知中进⾏响应内容加密。⼆、接下来我们看⼀下声明式事务的处理。在springboot中如果⽤到事务只需要在service⽅法上注解@Transactional,这⾥需要注意⼀点
@Transactional 默认只捕获RuntimeException.class对Exception异常得需要 @Transactional(rollbackFor = {Exception.class}) 捕获回滚。 Exception和RuntimeException的区别可以看这个链接()。如果项⽬内和数据库交互特别多的时候,在每个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());
}
}
我们定义了两种事务规则,⼀种是对于查询的只读事务readOnly,另⼀种是插⼊、更新等操作的事务required。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论