【Spring】使用Spring实现AOP

记录跟着狂神学Spring的历程(第20集)~

1. 导包

导入aop织入包

xml 复制代码
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>

2. 方式一:xml配置文件+Spring接口

xml 复制代码
<?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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/aop 
           http://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="userService" class="com.pojo.UserServiceImpl"/>
    <bean id="log" class="com.pojo.Log"/>
    
    <aop:config>
        <!-- 切入点:要在哪里切入 -->
        <!-- 方式1 execution 匹配指定类的所有方法 --> 
        <aop:pointcut id="pointcut" expression="execution(* com.pojo.service.UserServiceImpl.*.*(..))"/> 
        <!-- 方式2:用within简化(等价,更简洁) --> 
        <aop:pointcut id="pointcut" expression="within(com.pojo.service.UserServiceImpl.*)"/>
        
        
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
    </aop:config>
    
</beans>
  • expression: 就是 AOP 的筛选规则------ 告诉 Spring 要把增强逻辑(比如前置日志)织入到哪些方法上。
  • execution语法:execution( 修饰符 返回值类型 包名.类名.方法名(参数类型) 异常类型 )

然后写一个Log类,实现aop里的接口,比如MethodBeforeAdvice、AfterReturningAdvice

java 复制代码
@Test
public void test(){
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    UserService userService = (UserService)context.getBean("userService");
    userService.add();
}

会输出日志。

3.方式二:自定义切面

定义一个日志类(切面)

Java 复制代码
public class Diy{

  public void before(){
    System.out.println("方法执行前");
  }

  public void after(){
    System.out.println("方法执行后");
  }
}
xml 复制代码
<?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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/aop 
           http://www.springframework.org/schema/aop/spring-aop.xsd">
    
    <!-- 自定义的切面注册到bean中 -->
    <bean id="diy" class="com.pojo.Diy"/>
    
    <aop:config>
        <!-- 设置切面 ref代表要引用的类 -->
        <aop:aspect ref="diy">
            <!-- 切入点 匹配指定类的所有方法 -->
            <aop:pointcut id="pointcut" expresssion="execution(* com.pojo.service.UserServiceImpl.*.*(..))"/>    
            <!-- 通知 -->
            <aop:before method="before" pointcut-ref="pointcut"/>
            <aop:before method="after" pointcut-ref="pointcut"/>
        </aop:aspect>            
    </aop:config>
    
</beans>

<aop:before method="before" pointcut-ref="point"/>:切入点前通知,这里的before方法是自定义的类Diy里的before方法。

4. 注解版

Java 复制代码
@Aspect
public class MyAspect{

  @Before("execution=(* com.pojo.service.UserServiceImpl.*(..))")
  public void before(){
    System.out.println("方法执行前");
  }

  @After("execution=(* com.pojo.service.UserServiceImpl.*(..))")
  public void after(){
    System.out.println("方法执行后");
  }
  
  // 环绕
  @After("execution=(* com.pojo.service.UserServiceImpl.*(..))")
  public void around(){
    System.out.println("方法环绕");
  }
} 

@Aspect: 标注这个类是一个切面。

@Before: 等价于

<aop:pointcut id="pointcut" expresssion="execution(* com.pojo.service.UserServiceImpl.*.*(..))"/>

<aop:before method="before" pointcut-ref="pointcut"/>

xml 复制代码
<?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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/aop 
           http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 启用AOP注解支持 -->
    <aop:aspectj-autoproxy/>
    
    <!-- 定义一个切面 -->
        <bean id="myAspect" class="com.pojo.MyAspect"/>
    
    <!-- 定义一个被通知的对象 -->
    <bean id="myService" class="com.example.MyService"/>
    
</beans>

参考视频:20、AOP实现方式一_哔哩哔哩_bilibili22、注解实现AOP_哔哩哔哩_bilibili

相关推荐
Csvn11 小时前
📊 SQL 入门 Day 22:视图与物化视图
后端·sql
Csvn11 小时前
🐍 Day 4: Python 控制流 — 条件、循环与推导式的艺术
后端·python
2601_9537208211 小时前
【计算机毕业设计】基于Vue与Spring Boot的高校兼职信息服务平台设计与实现
spring boot·后端·课程设计
再吃一根胡萝卜13 小时前
用 Rust 写一个桌面悬浮图标:为什么它比 Python 更适合 AI 桌面工具?
后端
IT_陈寒13 小时前
Vue的computed属性把我坑惨了,原来我一直用错姿势
前端·人工智能·后端
evans在进步14 小时前
Spring Boot 核心机制详解:可执行 JAR、CORS、静态资源与配置绑定
spring boot·后端·jar
Sayuanni%314 小时前
SpringBoot 从注解到源码:核心知识点总结
java·spring boot·后端
陈随易15 小时前
Bun v1.4 更新总结:把浏览器、图片、定时任务和工程工具都装进一个运行时
前端·后端·程序员
人间凡尔赛16 小时前
2026 后端架构三驾马车:Wasm 容器上 K8s、存算分离与 AI 原生
后端·云原生·架构
凤山老林16 小时前
动态 i18n 体系落地:Spring Boot 多租户热加载与前后端协同实践
java·spring boot·后端·i18n