版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011171125/article/details/85811520
AOP前置通知
前置通知:在方法之前执行的通知,使用`@Before`注解并将切入点表达式的值作为注解值。
- 使用Maven添加依赖的jar包:
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.1.2.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-core --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.1.3.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.1.3.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.1.3.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.1.3.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.8</version> </dependency>
- 继续使用上节中的
ArithmeticCalculator
和ArithmeticCalculatorImpl
类。 - 新建一个
LoggingAspect
切面类:
其中@Component
注解标注为一个被Spring管理的bean,@Aspect
将类标注为切面类;execution(* com.fafa.spring.aop.impl.*.*(..))
为execution(public int com.fafa.spring.aop.impl.ArithmeticCalculator.add(int, int))
的抽象精简写法,第一个*
代表匹配任意修饰符及任意返回值,第二个*
表示com.fafa.spring.aop.impl
包中的任意类,第三个*
表示类中的任意方法,括号中的..
表示方法的任意参数。// 把这个类声明为一个切面: 需要把该类放入到IOC容器中,再声明为一个切面 @Component @Aspect public class LoggingAspect { // 声明该方法是一个前置通知:在目标方法开始之前执行 // @Before("execution(public int com.fafa.spring.aop.impl.ArithmeticCalculator.add(int, int))") @Before("execution(* com.fafa.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..." + args); } }
JoinPoint
参数表示连接点,可以获取到方法名和参数。 - 创建一个Spring配置文件
applicationContext.xml
使用@AspectJ
注解会自动为匹配的类生成代理对象:<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<?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/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd"> <!-- 配置自动扫描的包 --> <context:component-scan base-package="com.fafa.spring.aop.impl"></context:component-scan> <!-- 使AspectJ注解起作用 :自动为匹配的类生成代理对象--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
- 创建测试类:
测试结果:在方法返回值前都添加了相应的信息public class Main { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:applicationContext.xml"); ArithmeticCalculator arithmeticCalculator = ctx.getBean(ArithmeticCalculator.class); int result = arithmeticCalculator.add(3, 6); System.out.println("result:" + result); result = arithmeticCalculator.div(6, 3); System.out.println("result:" + result); } }
The methodadd begins...[3, 6] result:9 The methoddiv begins...[6, 3] result:2
后置通知
- 使用
@After
注解标注,在LoggingAspect
类中添加如下方法:// 后置通知就是在目标方法执行后(无论是否发生异常),都会执行的通知 // 在后置通知中还不能访问目标方法执行的结果。 @After("execution(* com.fafa.spring.aop.impl.*.*(..))") public void afterMethod(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); System.out.println("The method "+methodName+" ends..."); }
- 运行结果:
The methodadd begins...[3, 6] The method add ends... result:9 The methoddiv begins...[6, 3] The method div ends... result:2
afterMethod
方法结束,此时还无法在结束时获取到返回的结果,后面可以使用返回通知获取到返回值。