- 关于Spring AOP
一些核心概念
常用注解
@EnableAspectJAutoProxy
@Aspect
@Pointcut
@Before
@After / @AfterReturning / @AfterThrowing
@Around
@Order
切入点execution表达式语法参考spring官网:
https://docs.spring.io/spring/docs/5.1.9.RELEASE/spring-framework-reference/core.html#aop-pointcuts-combining
- 通过注解的方式,使用AOP进行日志记录
自定义了@Log注解,用来描述某个方法
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
String description() default "";
}
定义切面类
@Aspect
@Component
@Slf4j
public class MyAspect {
//计算方法执行的时间,并记录到日志
@Around("serviceOps()")
public Object myPerformance(ProceedingJoinPoint pjp) {
long starttime = System.currentTimeMillis();
try {
return pjp.proceed();
} catch (Throwable t) {
return "N";
} finally {
long endtime = System.currentTimeMillis();
log.info("方法名称:{} 耗时:{} ms",pjp.getSignature().getName(),endtime - starttime);
}
}
//定义切入点
@Pointcut("execution(* com.example.MyBatisDemo.service..*(..))")
private void serviceOps() {}
//方法执行前,记录对应方法的描述
@Before("serviceOps()")
public void beforeOps(JoinPoint joinPoint){
try{
log.info("方法描述:{}",getMethodDescription(joinPoint));
}catch (Exception e){
e.printStackTrace();
}
}
//获取方法的描述
private static String getMethodDescription(JoinPoint joinPoint) throws Exception{
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
//log.info("\ntargetName:{},methodName:{}",targetName,methodName);
Object[] arguments = joinPoint.getArgs();
//log.info("args:{}",arguments);
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
//log.info("\ntargetClass:{},methods:{}",targetClass.getName(),methods);
String description = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] classes = method.getParameterTypes();
//log.info("parameterTypes:{}",classes);
if (classes.length == arguments.length) {
description = method.getAnnotation(Log.class).description();
break;
}
}
}
return description;
}
}
service层
@Service
public class UserService {
@Resource
private UserMapper userMapper;
@Log(description = "通过name查找用户信息")
public User findByName(String name){
return userMapper.findByName(name);
}
}
调用service层的方法
@SpringBootApplication
@MapperScan("com.example.MyBatisDemo.mapper")
@EnableAspectJAutoProxy
public class MyBatisDemoApplication implements ApplicationRunner {
@Resource
private UserService userService;
public static void main(String[] args) {
SpringApplication.run(MyBatisDemoApplication.class, args);
}
@Override
public void run(ApplicationArguments args) throws Exception {
User user1 = userService.findByName("lkwykn");
System.out.println(user1.toString());
}
}
结果