AspectJ 支持 5 种类型的通知注解:
- @Before: 前置通知, 在方法执行之前执行
- @After: 后置通知, 在方法执行之后执行 。
- @AfterRunning: 返回通知, 在方法返回结果之后执行
- @AfterThrowing: 异常通知, 在方法抛出异常之后
- @Around: 环绕通知, 围绕着方法执行
SpringAop自定义切面切点
配置一个切面(要使用两个注解,1.@Aspect声明该类是一个切面,Spring官方文档解释,单单这个注解不能把该类注册成bean 。所以需要加入2.@Component注解)
- 第一种方式
/**
* @Description:自定义注解
* @Author:YJG
* @Date 9:24 2020/5/25
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Custome {
String value() default "custom";
}
//$##############################################
@Aspect
@Component
public class CustomAspect{
/**
* 切点: 所有配置 DataSource 注解的方法
*/
@Pointcut("@annotation(com.alimather.common.Custome)")
public void customPointCut() {}
@Around(customPointCut())
Public Object myPorintCut(){
}
}
- 第二种:直接在切面中使用(实现日志监控输出)
@Slf4j
@Aspect
@Component
public class ControlLogAspect {
/**
* execution:表达式主体
* 第一部分 代表方法返回值类型 *表示任何类型
* 第二部分 com.alimather.*service.service 表示要监控的包名
* 第三部分 .. 代表当前包名以及子包下的所有方法和类
* 第四部分 * 代表类名,*代表所有的类
* 第五部分 *(..) *代表类中的所有方法(..)代表方法里的任何参数
*/
@Around("execution(* com.alimather.*service.service..*.*(..))")
public Object controlServiceImplLog(ProceedingJoinPoint joinPoint) throws Throwable {
Class<?> aClass = joinPoint.getTarget().getClass();
String name = joinPoint.getSignature().getName();
Long beginTime = System.currentTimeMillis();
log.info(" <== 开始执行{}.{}",aClass,name);
Object proceed = joinPoint.proceed();
Long useTime = System.currentTimeMillis() - beginTime;
if(useTime > ExecuteTimeEnum.ERROR_TIME.getTime()) {
log.error(" <== {}方法执行结束,耗时{}ms",name,useTime);
} else if (useTime > ExecuteTimeEnum.WARN_TIME.getTime()){
log.warn(" <== {}方法执行结束,耗时{}ms",name,useTime);
} else {
log.info(" <== {}方法执行结束,耗时{}ms",name,useTime);
}
return proceed;
}
}
- 切点定义案例:
@Aspect
public class SystemArchitecture {
/**
* A join point is in the web layer if the method is defined
* in a type in the com.xyz.someapp.web package or any sub-package
* under that.
*/
@Pointcut("within(com.xyz.someapp.web..*)")
public void inWebLayer() {}
/**
* A join point is in the service layer if the method is defined
* in a type in the com.xyz.someapp.service package or any sub-package
* under that.
*/
@Pointcut("within(com.xyz.someapp.service..*)")
public void inServiceLayer() {}
/**
* A join point is in the data access layer if the method is defined
* in a type in the com.xyz.someapp.dao package or any sub-package
* under that.
*/
@Pointcut("within(com.xyz.someapp.dao..*)")
public void inDataAccessLayer() {}
/**
* A business service is the execution of any method defined on a service
* interface. This definition assumes that interfaces are placed in the
* "service" package, and that implementation types are in sub-packages.
*
* If you group service interfaces by functional area (for example,
* in packages com.xyz.someapp.abc.service and com.xyz.someapp.def.service) then
* the pointcut expression "execution(* com.xyz.someapp..service.*.*(..))"
* could be used instead.
*
* Alternatively, you can write the expression using the 'bean'
* PCD, like so "bean(*Service)". (This assumes that you have
* named your Spring service beans in a consistent fashion.)
*/
@Pointcut("execution(* com.xyz.someapp..service.*.*(..))")
public void businessService() {}
/**
* A data access operation is the execution of any method defined on a
* dao interface. This definition assumes that interfaces are placed in the
* "dao" package, and that implementation types are in sub-packages.
*/
@Pointcut("execution(* com.xyz.someapp.dao.*.*(..))")
public void dataAccessOperation() {}
}
对于execution和within的区别我不是很明白,欢迎大佬评论讲解!