【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

相关推荐
李日灐2 小时前
C++STL:仿函数、模板(进阶) 详解!!:“伪装术”和模板特化、偏特化的深度玩法指南
开发语言·c++·后端·stl
何中应2 小时前
使用Spring自带的缓存注解维护数据一致性
java·数据库·spring boot·后端·spring·缓存
一路向北⁢2 小时前
企业级敏感词拦截检查系统设计方案(Spring Boot)
spring boot·后端·bootstrap·敏感词·敏感词拦截
Honmaple2 小时前
DeepSeek-OCR + AgentScope:打造私有化智能文档处理智能体
后端
野犬寒鸦2 小时前
从零起步学习RabbitMQ || 第一章:认识消息队列及项目实战中的技术选型
java·数据库·后端
老毛肚2 小时前
Spring源码探究1.0
java·后端·spring
源代码•宸2 小时前
Golang原理剖析(程序初始化、数据结构string)
开发语言·数据结构·经验分享·后端·golang·string·init
小鸡脚来咯3 小时前
RESTful API 面试详解
后端·面试·restful