1. 切面 (Aspect)
- 切面,切入点和通知的抽象,定义切入点和通知
- @Aspect 声明当前类是一个切面
1.1 Advice 注解
- @Before
- @Around
- @After
- @AfterReturning
- @AfterThrowing
@Aspect
@Component
public class LoggerAspect {
@Around(value = "execution(* com.example.concrete.starter.service.*.*(..))")
public Object aroundCut(ProceedingJoinPoint point) throws Throwable {
System.out.println("around...");
return point.proceed();
}
}
1.2 切点 + 增强
- @Pointcut("匹配规则")
- @Pointcut:
@Aspect
@Component
public class LogCut {
// 定义切点
@Pointcut(value = "execution(* com.example.concrete.starter.service.*.*(..))")
public void pointCut() {}
@Before(value = "pointCut()")
public void before(JoinPoint joinPoint) {
// ...
}
}
2. 注解拦截
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogAnno {
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AfterAnno {
}
2.1 拦截类下面所有方法
@LogAnno
@AfterAnno
@Service
public class GreetServiceImpl implements GreetService {
@Override
public String greeting(UserDTO userDTO, String env) {
return "greeting run..." + JSON.toJSONString(userDTO) + "; " + env;
}
}
@Aspect
@Component
public class LoggerAspect {
@Pointcut("@annotation(com.example.concrete.starter.intercept.aop.LogAnno)")
public void pointCut() {}
@Before("pointCut()")
public void before(JoinPoint joinPoint) {
System.out.println("before...");
}
@Around("pointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
System.out.println("around start");
Object obj = point.proceed();
System.out.println("around end");
return obj;
}
@Pointcut("@annotation(com.example.concrete.starter.intercept.aop.AfterAnno)")
public void afterCut() {}
// 复合切点
@After("pointCut() && afterCut()")
public void after() {
System.out.println("after...");
}
}
22. 拦截方法
@Service
public class GreetServiceImpl implements GreetService {
@Override
@LogAnno
@AfterAnno
public String greeting(UserDTO userDTO, String env) {
return "greeting run..." + JSON.toJSONString(userDTO) + "; " + env;
}
}
3. 表达式拦截
@Aspect
@Component
public class ExecutionAspect {
@AfterReturning(value = "execution(* com.example.concrete.starter.service.*.*(..))", returning = "result")
public void AfterReturning(JoinPoint joinPoint, Object result) {
Object[] args = joinPoint.getArgs();
System.out.println("after returning: " + JSON.toJSONString(args));
System.out.println("after result: " + JSON.toJSONString(result));
}
}
3.1 切入点表达式
- 格式
execution([修饰符] 返回值类型 包名.类名.方法名(参数))
-
.*.*
表示所有包的所有方法,(..)
方法参数
# 匹配 GreetServiceImpl#greet
execution(public String com.example.concrete.starter.service.impl.GreetServiceImpl.greet(Integer))
# 匹配 GreetServiceImpl 类的任意 greet 方法
execution(* com.example.concrete.starter.service.impl.GreetServiceImpl.greet(..))
# 匹配 GreetServiceImpl 类的所有方法
execution(* com.example.concrete.starter.service.impl.GreetServiceImpl.*(..))
# 匹配 service 包 (包含子包) 所有 public 方法
execution(public * com.example.concrete.starter.service.*.*(..))
# 匹配 service 包 (包含子包) 所有类的所有方法
execution(* com.example.concrete.starter.service.*.*(..))
# 可选:匹配 service 包及其子包,两个点(..)
execution(* com.example.concrete.starter.service..*.*(..))
4. XML 配置方式
- 官方文档
https://docs.spring.io/spring-framework/docs/3.0.x/reference/aop.html
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
https://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 开启自动扫描 -->
<context:component-scan base-package="com.example.concrete.starter"/>
<!-- 配置 AOP 代理 -->
<aop:aspectj-autoproxy/>
</beans>
<aop:config>
<aop:aspect id="myAspect" ref="aspectBeanName">
<aop:pointcut id="pointcutMethodName" expression="execution(* com.example.concrete.service..*.*(..))" />
<aop:before method="beforMethodName" pointcut-ref="pointcutMethodName" />
<aop:aspect>
</aop:config>
网友评论