【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实现方式一_哔哩哔哩_bilibili 到 22、注解实现AOP_哔哩哔哩_bilibili

相关推荐
码事漫谈4 分钟前
黄仁勋被裁第一天,就收到了橄榄枝
后端
金銀銅鐵39 分钟前
带您看懂字节码指令(二):空循环里有什么
java·后端·ai编程
皮皮林5512 小时前
比 Xshell 还好用的 SSH 客户端神器,MobaXterm 太爱了!
后端
我不会起名字3223 小时前
会话缓存失效排查:区分 Redis 失效与节点广播
redis·后端·go·即时通讯·im·故障排查
深入云栈5 小时前
Netty 4.2.x 源码深度解析 (二十三):ByteBuf 核心设计 —— 索引、类型与零拷贝
java·后端·架构
JackJiang5 小时前
IM踩坑:聊天消息ID怎么设计?一个UUID搞不定,我用双ID解决
后端·架构
开心猴爷5 小时前
iOS 上架 App 流程
后端·ios
code_Bo5 小时前
不只命令行:我把跨 Agent 会话同步做成了桌面应用
前端·javascript·后端
用户8356290780516 小时前
使用 Python 控制 Excel 工作表的分页位置
后端·python
用户8356290780516 小时前
Python 如何在 Word 中添加和管理文档变量
后端·python