【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

相关推荐
程序员张328 分钟前
SpringBoot集成BCrypt密码加密库
java·spring boot·后端
CaffeinePro35 分钟前
FastAPI数据库集成SQLAlchemy异步ORM全方案
后端·fastapi
小旭Coding38 分钟前
凌晨告警轰炸!Go 服务协程只增不减,内存持续暴涨直至 OOM
后端
半个落月41 分钟前
用 LangChain.js 手写一个能读写文件和执行命令的 Mini Cursor
javascript·人工智能·后端
952362 小时前
RabbitMQ-基础操作
java·spring boot·分布式·后端·spring·rabbitmq
柒和远方2 小时前
从审计日志到可下载证据包:事务型 Outbox、租约 fencing 与保留水位
前端·后端·架构
geovindu3 小时前
CSharp: Prototype Pattern
开发语言·后端·设计模式·.net·原型模式·创建型模式
Listen·Rain4 小时前
Springboot整合Ollama实现调用本地多模型
java·spring boot·后端
张三丰24 小时前
Agent 不只是聊天框:用 ArkUI 做一个鸿蒙任务工作台
后端
卷无止境4 小时前
从Python的cryptography库出发,从零开始理解密码学,到构建零信任网络
后端·python