第一章:环境搭建

  • IDEA 2021+。
  • JDK 11+。
  • Maven 3.8。

  • pom.xml

  1. <!-- Spring -->
  2. <dependency>
  3. <groupId>org.springframework</groupId>
  4. <artifactId>spring-context</artifactId>
  5. <version>5.3.12</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.springframework</groupId>
  9. <artifactId>spring-aspects</artifactId>
  10. <version>5.3.12</version>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.springframework</groupId>
  14. <artifactId>spring-test</artifactId>
  15. <version>5.3.12</version>
  16. </dependency>
  17. <!-- junit单元测试 -->
  18. <dependency>
  19. <groupId>junit</groupId>
  20. <artifactId>junit</artifactId>
  21. <version>4.13.2</version>
  22. <scope>test</scope>
  23. </dependency>

第二章:准备的接口、实现类和切面类

2.1 准备的接口

  • Calculator.java
  1. package com.github.fairy.era.aop;
  2. /**
  3. * 计算器
  4. *
  5. * @author 许大仙
  6. * @version 1.0
  7. * @since 2021-11-08 08:50
  8. */
  9. public interface Calculator {
  10. int add(int a, int b);
  11. int sub(int a, int b);
  12. int mul(int a, int b);
  13. int div(int a, int b);
  14. }

2.2 准备的实现类

  • CalculatorImpl.java
package com.github.fairy.era.aop.impl;

import com.github.fairy.era.aop.Calculator;
import org.springframework.stereotype.Component;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-08 08:51
 */
public class CalculatorImpl implements Calculator {
    @Override
    public int add(int a, int b) {
        return a + b;
    }

    @Override
    public int sub(int a, int b) {
        return a - b;
    }

    @Override
    public int mul(int a, int b) {
        return a * b;
    }

    @Override
    public int div(int a, int b) {
        return a / b;
    }
}

2.3 准备的切面类

  • LogAspect.java
package com.github.fairy.era.aop.aspect;

import org.aspectj.lang.JoinPoint;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-08 08:54
 */
public class LogAspect {

    public void printLogBefore() {
        System.out.println("[AOP前置通知] 方法开始了");
    }

    public void printLogAfterReturn(Object targetMethodReturnValue) {
        System.out.println("[AOP返回通知] 方法的返回值是:" + targetMethodReturnValue);
    }

    public void printLogAfterThrowing(JoinPoint joinPoint, Throwable targetMethodException) {
        System.out.println("[AOP异常通知] 方法:" + joinPoint.getSignature().getName() + "抛出了异常,异常类型是:" + targetMethodException.getClass().getName());
    }

    public void printLogAfter() {
        System.out.println("[AOP最终通知] 方法开始了");
    }
}

第三章:配置 Spring 配置文件

  • applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 配置目标类 -->
    <bean id="calculator" class="com.github.fairy.era.aop.impl.CalculatorImpl"></bean>
    <!-- 配置切面类 -->
    <bean id="logAspect" class="com.github.fairy.era.aop.aspect.LogAspect"></bean>

    <!-- 配置AOP -->
    <aop:config>
        <!-- 配置切入点表达式 -->
        <aop:pointcut id="pointcut" expression="execution(* *..*.*(..))"/>
        <!-- aop:aspect标签:配置切面 -->
        <!-- ref属性:关联切面类的bean -->
        <aop:aspect ref="logAspect">
            <!-- aop:before标签:配置前置通知 -->
            <!-- method属性:指定前置通知的方法名 -->
            <!-- pointcut-ref属性:引用切入点表达式 -->
            <aop:before method="printLogBefore" pointcut-ref="pointcut"></aop:before>
            <!-- aop:after-returning标签:配置返回通知 -->
            <!-- returning属性:指定通知方法中用来接收目标方法返回值的参数名 -->
            <aop:after-returning
                    method="printLogAfterReturn"
                    pointcut-ref="pointcut"
                    returning="targetMethodReturnValue"/>
            <!-- aop:after-throwing标签:配置异常通知 -->
            <!-- throwing属性:指定通知方法中用来接收目标方法抛出异常的异常对象的参数名 -->
            <aop:after-throwing
                    method="printLogAfterThrowing"
                    pointcut-ref="pointcut"
                    throwing="targetMethodException"/>
            <!-- aop:after标签:配置后置通知 -->
            <aop:after method="printLogAfter" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>

</beans>

第四章:测试

package com.github.fairy.era.bean;

import com.github.fairy.era.aop.Calculator;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 11:02
 */
@RunWith(SpringRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpringTest {

    @Autowired
    private Calculator calculator;

    @Test
    public void test() {
        int add = calculator.add(1, 2);
        System.out.println("add = " + add);
    }
}