概念
- advice/通知: 什么时候干什么事情
- pointcut/切点: 什么地方可以干这个事情
- advice与pointcut组成切面/aspect,在什么地方什么时候干什么事情
- joinpoint:软件中的连接点,这些点可以织入切面。
五种通知类型
- before
- after
- after-returning
- after-throwing
- around
xml配置方式
<bean id="logAspect" class="com.lbl.LogAspect"></bean>
<aop:config>
<aop:pointcut expression="execution(* com.lbl.*.*(..))" id="pointcut" />
<aop:aspect ref="logAspect">
<aop:before method="before" pointcut-ref="pointcut" />
<aop:after method="after" pointcut-ref="pointcut" />
</aop:aspect>
</aop:config>
注意,方法如果是private,则不能拦截到!另外,方法为private时还出现autowired的对象获取不到报空指针的情况。
注解方式
- 使用xml开启
<aop:aspectj-autoproxy />
- 使用注解开启
@EnableAspectJAutoProxy
- 使用注解声明Aspect
//这两个标签都必须有
@Aspect
@Component
public class LogAspect{
@Before("execution(* com.lbl.controller.*.*(..))")
public void before(){
System.out.println("before");
}
@After("execution(* com.lbl.controller.*.*(..))")
public void after(){
System.out.println("after");
}
}
- 要获取参数,可以传入JoinPoint或者ProceedingJoinPoint(around类型的通知才可以传这个)
@Around("execution(* com.lbl.controller.*.*(..))")
public void around(ProceedingJoinPoint pjp){
Arrays.stream(pjp.getArgs()).forEachOrdered(obj ->{
System.out.println(obj);
});
Object obj = pjp.proceed();
System.out.println(obj);
}
- 组合切点条件
@Around("!execution(* com.lbl.controller.PointCut.*(..)) &&"
+ "execution(* com.lbl.controller.*.*(..))")
- 重复使用切点
@Pointcut(value ="execution(* com.lbl.controller.*.*(..))")
public void pointcut1(){}
@Before("pointcut1()")
注意:如果报错可能是包版本太低(注意依赖的groupId是org.aspectj)