SpringAop @Pointcut(“@annotation“)\@Aspect练习
切面记录日志
切面类
@Slf4j
@Aspect
@Component
public class AspectForFeign {
@Pointcut("execution(public * com.keke.remote..*Feign.*(..))")
public void pointcut() {
}
@Around("pointcut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
log.info("@Around:开始执行目标方法:{}ms", start);
Object result = null;
try {
result = joinPoint.proceed();
} catch (Exception e) {
System.out.println(e.getMessage());
}
long end = System.currentTimeMillis();
log.info("@Around:结束执行目标方法:{}ms", end);
//获取方法签名
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
String methodName = methodSignature.getName();
log.info("方法名:{} 耗时:{}ms", methodName, end - start);
//如果不返回result,则目标对象实际返回值会被置为null
return result;
}
- 注意:返回结果如果不返回result,则目标对象实际返回值会被置为null
@Component
- 需要将切面类配置为bean
@Aspect
- 标记为切面类
@Pointcut
需要表达式命名,而不需要在方法体内编写实际代码。
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)
@Around
环绕增强,@Pointcut和@Around联合使用等同于:
@Around(“execution(public com.keke.remote..Feign.*(..))”)
切点拦截记录访问日志
拦截器数据源
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)//注解在方法上
public @interface ApiAccess{
}
拦截器业务实现代码
@Aspect
@Component
@Slf4j
public class ApiAccessAspect {
@Pointcut("@annotation(com.keke.annotation.ApiAccess)")
public void pointcut() {
}
@Around("pointcut()")
public Object apiAccessAspect(ProceedingJoinPoint joinPoint) throws Throwable {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
log.info("url:{}被访问了.....",request.getRequestURL().toString());
return joinPoint.proceed(joinPoint.getArgs());
}
}
@Pointcut的表达式-@annotation
限制连接点的匹配,其中连接点的主题(在 Spring AOP 中执行的方法)具有给定的 annotation。
官方案例:
任何连接点(仅在 Spring AOP 中执行方法),其中执行方法具有@Transactional
annotation:
@annotation(org.springframework.transaction.annotation.Transactional)
官方的案例已经说的很清楚了,就是@annotation是匹配拥有指定注解的方法的。这里要注意,@annotation只匹配实现类中的有注解的方法,不会匹配接口中的注解方法。
看案例:
我们准备接口:
/**
* @description
*/
public interface IBookService {
//@DkAnnotation// 这里的注解是不会被匹配的
public void saveBook(String title);
}
实现类:
/**
* @description
*/
@Component
public class BookService implements IBookService{
@Override
@DkAnnotation //这里的注解会被匹配
public void saveBook(String title){
System.out.println("保存图书:"+title);
}
public void saveBook(String title,int count){
System.out.println("保存"+title+","+count+"次");
}
}
修改Aspect类:
/**
* @description
*/
@Component //将当前bean交给spring管理
@Aspect //定义为一个AspectBean
public class DkAspect {
//使用@annotation配置匹配所有还有指定注解的方法
@Pointcut("@annotation(com.st.dk.demo7.annotations.DkAnnotation)")
private void pointCut1(){
}
//定义一个前置通知
@Before("pointCut1()")
private static void befor(){
System.out.println("---前置通知---");
}
}
测试:
@Test
public void testAopPoint_annotation(){
ApplicationContext ac =
new AnnotationConfigApplicationContext(Appconfig.class);
IBookService bean = ac.getBean(IBookService.class);
bean.saveBook("程序员的修养");
}
结果:
还没有评论,来说两句吧...