【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

相关推荐
立心者01 小时前
SpringBoot中使用TOTP实现MFA(多因素认证)
java·spring boot·后端
AskHarries2 小时前
SEO 页面怎么生成
后端
爱吃牛肉的大老虎2 小时前
Rust对象之结构体,枚举,特性
开发语言·后端·rust
石榴2 小时前
NestJS 的请求到底经过了什么:装饰器、守卫、拦截器、管道与中间件如何配合
后端
Gopher_HBo2 小时前
moby-client客户端
后端
杨运交3 小时前
[055][调度模块]Spring动态任务调度框架的设计与实现
java·后端·spring
卷福同学4 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端
Csvn5 小时前
📊 SQL 入门 Day 11:CASE 表达式:SQL 里的 if-else 魔法
后端·sql
QQ_21696290965 小时前
Spring Boot 养老院管理系统:从入住、护理到费用结算的全流程实现(源码可领)
java·spring boot·后端
万少7 小时前
DeepSeek-V4-Flash 正式版上线了,但这 3 个坑我帮你提前踩了
前端·javascript·后端