springboot使用AOP
1.Aop是面向切面的,为程序定义一个切面,并在切面处定义想要做的事(记录日志,方法入参,返回值,抛出异常等)。当程序执行到切面处,即会执行你想要程序做的事。
2.这里介绍简单的使用(对所有service方法记录日志),包括以下几个注解@Aspect,@Component,@Pointcut,@Before,@AfterReturning,@AfterThrowing。
3.开始实现
1.使用AOP需要导入其依赖,之后创建一个类,随便命名,这里叫做ServiceAspectLogConfig,意思对Service方法创建切点的配置类。在类上添加@Aspect和@Component注解,表示该类是AOP切面类,并将其交给spring容易管理。
<!-- AOP -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
@Aspect
@Component
public class ServiceAspecJLogConfig {
public static Logger logger = LoggerFactory.getLogger(ServiceAspecJLogConfig.class);
}
2.定义切面方法serviceLog,使用注解@Pointcut表示该方法是切面方法,注解内定义切面的位置
@Pointcut(value = "execution(public * com.xxx.modules.service.impl.*ServiceImpl.*(..))"
+ " || execution(public * com.xxx.modules.activity.service.impl.*ServiceImpl.*(..))")
public void serviceLog() { }
注解内的value属性表示切面定义的位置,execution表示匹配方法执行的连接点,里面的表达式格式:修饰符——返回值——方法全类名——方法参数。其中*表示全部匹配,即任意。…表示任意个。以上两个表达式表示com包下modules.service.impl下的所有以ServiceImpl结尾的带有任意参数的任意返回值的public方法和com包下modules.activity.service.impl下的下的所有以ServiceImpl结尾的带有任意参数的任意返回值的public方法。具体语法使用可以参考这篇文章AOP语法详解。
3.定义好切点后,spring会为满足条件的方法添加切点,接下来就是在程序执行到切点之前、之后、以及抛出异常该做的事。
4.使用@Before注解在进入切面方法之前记录方法入参
@Before(value = "serviceLog()")
public void beforeServiceLog(JoinPoint joinPoint) {
StringBuffer sb = new StringBuffer(joinPoint.getSignature().toShortString());
sb.append("--entry args: " + Arrays.toString(joinPoint.getArgs()));
logger.info(sb.toString());
}
通过日志记录切面方法签名,以及方法入参。注解value值表示定义的切点方法名
5.使用@AfterReturing注解在执行切面方法之后记录方法返回值
@AfterReturning(value = "serviceLog()", returning = "returnObj")
public void afterServiveLog(JoinPoint joinPoint, Object returnObj) {
StringBuffer sb = new StringBuffer(joinPoint.getSignature().toShortString());
if(returnObj == null) {
sb.append("--return object: null");
} else {
sb.append("--return object: " + returnObj.toString());
}
logger.info(sb.toString());
}
6.使用@AfterThrowing注解早在切面方法抛出异常后记录异常信息
@AfterThrowing(value = "serviceLog()", throwing = "exception")
public void handlerThrowingException(JoinPoint joinPoint, Exception exception) {
StringBuffer sb = new StringBuffer(joinPoint.getSignature().toShortString());
sb.append("--exception msg: " + exception.getMessage());
logger.info(sb.toString());
}
7.这是自己对AOP的一次尝试,理解还不够,有什么不对可以提出来,不喜勿喷哦~。下面是完整代码
@Aspect
@Component
public class ServiceAspecJLogConfig {
public static Logger logger = LoggerFactory.getLogger(ServiceAspecJLogConfig.class);
/**
* Title: serviceLog
* Description: 对所有ServiceImpl的public方法插入切面
* Date: 2019年8月1日
* void
*/
@Pointcut(value = "execution(public * com.zjzy.ding.ding.modules.service.impl.*ServiceImpl.*(..))"
+ " || execution(public * com.zjzy.ding.terminal.modules.activity.service.impl.*ServiceImpl.*(..))")
public void serviceLog() { }
/**
* Title: beforeServiceLog
* Description: 针对切面方法执行之前需要执行的方法,记录方法名以及方法入参
* Date: 2019年8月1日
* void
*/
@Before(value = "serviceLog()")
public void beforeServiceLog(JoinPoint joinPoint) {
StringBuffer sb = new StringBuffer(joinPoint.getSignature().toShortString());
sb.append("--entry args: " + Arrays.toString(joinPoint.getArgs()));
logger.info(sb.toString());
}
/**
* Title: afterServiveLog
* Description: 针对切面方法返回之后需要执行的方法,记录方法名以及返回值
* Date: 2019年8月1日
* void
*/
@AfterReturning(value = "serviceLog()", returning = "returnObj")
public void afterServiveLog(JoinPoint joinPoint, Object returnObj) {
StringBuffer sb = new StringBuffer(joinPoint.getSignature().toShortString());
if(returnObj == null) {
sb.append("--return object: null");
} else {
sb.append("--return object: " + returnObj.toString());
}
logger.info(sb.toString());
}
/**
* Title: handlerThrowingException
* Description: 针对切面方法发生异常后需要执行的方法,记录当前方法名以及抛出的异常信息
* Date: 2019年8月1日
* void
*/
@AfterThrowing(value = "serviceLog()", throwing = "exception")
public void handlerThrowingException(JoinPoint joinPoint, Exception exception) {
StringBuffer sb = new StringBuffer(joinPoint.getSignature().toShortString());
sb.append("--exception msg: " + exception.getMessage());
logger.info(sb.toString());
}
}