在学习之前先提一个概念。
AsprctJ:Java社区里最完整最流行的AOP框架。在Spring2.0以上版本中,可以使用基于AspectJ注解或基于XML配置的AOP。
启用AspectJ注解支持
- 要在 Spring 中声明 AspectJ 切面, 只需要在 IOC 容器中将切面声明为 Bean 实例. 当在 Spring IOC 容器中初始化 AspectJ 切面之后, Spring IOC 容器就会为那些与 AspectJ 切面相匹配的 Bean 创建代理.
- 在 AspectJ 注解中, 切面只是一个带有 @Aspect 注解的 Java 类.
- 通知是标注有某种注解的简单的 Java 方法.
- AspectJ 支持 5 种类型的通知注解:
- @Before: 前置通知, 在方法执行之前执行
- @After: 后置通知, 在方法执行之后执行
- @AfterRunning: 返回通知, 在方法返回结果之后执行
- @AfterThrowing: 异常通知, 在方法抛出异常之后
- @Around: 环绕通知, 围绕着方法执行
SpringAOP
1).加入jar包
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
spring-aop-4.3.11.RELEASE.jar
spring-aspects-4.3.11.RELEASE.jar
commons-logging-1.1.3.jar
spring-beans-4.3.11.RELEASE.jar
spring-context-4.3.11.RELEASE.jar
spring-core-4.3.11.RELEASE.jar
spring-expression-4.3.11.RELEASE.jar
2).在配置文件中加入aop的命名空间
3).基于注解的方式
①.在配置文件中加
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
②.把横切关注点的代码抽象到切面的类中
i.切面首先是一个IOC中的bean,即加入@Component注解
ii.切面还需要加入@Aspect注解
③.在类中声明各种通知
i.声明一个方法
ii.在方法前加入通知
- @Before: 前置通知, 在方法执行之前执行
- @After: 后置通知, 在方法执行之后执行
- @AfterRunning: 返回通知, 在方法返回结果之后执行
- @AfterThrowing: 异常通知, 在方法抛出异常之后
- @Around: 环绕通知, 围绕着方法执行
④.可以在通知方法中声明一个类型为JoinPoint的参数,然后就能访问链接细节,如方法名称和参数值
@Component
@Aspect
public class LoggingAspect {
//声明该方法是一个前置通知:在目标方法开始之前执行
@Before("execution(* com.jhh.spring.aop.impl.*.*(*, *))")
public void beforeMethod(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("The method " + methodName + " begins with " + args);
}
//后置通知:在目标方法执行后(无论是否发生异常)执行的通知
//在后置通知中还不能访问目标方法执行的结果,执行结果在返回通知中访问
@After("execution(* com.jhh.spring.aop.impl.*.*(*, *))")
public void afterMethod(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("The method " + methodName + " ends with " + args);
}
}
利用方法签名编写 AspectJ 切入点表达式
最典型的切入点表达式时根据方法的签名来匹配各种方法:
- execution * com.atguigu.spring.ArithmeticCalculator.(..): 匹配 ArithmeticCalculator 中声明的所有方法,第一个 代表任意修饰符及任意返回值. 第二个 * 代表任意方法. .. 匹配任意数量的参数. 若目标类与接口与该切面在同一个包中, 可以省略包名.
- execution public * ArithmeticCalculator.*(..): 匹配 ArithmeticCalculator 接口的所有公有方法.
- execution public double ArithmeticCalculator.*(..): 匹配 ArithmeticCalculator 中返回 double 类型数值的方法
- execution public double ArithmeticCalculator.*(double, ..): 匹配第一个参数为 double 类型的方法, .. 匹配任意数量任意类型的参数
- execution public double ArithmeticCalculator.*(double, double): 匹配参数类型为 double, double 类型的方法.