基于XML的AOP开发

AOP 为 Aspect Oriented Programming 的缩写,意思为面向切面编程

AOP相关术语:

目标对象(Target):

你要去代理的对象,可以理解为之前很单纯的那个对象。

代理对象(Proxy):

你把你那个单纯的对象给我,我给你一个更强的对象

连接点(Joinpoint):

所谓的连接点就是指哪些可以被拦截到的方法。

切入点(Pointcut):

对连接点再去具体一点,真正要拦截的方法

通知/增强(Advice):

你把方法拦截了,你要干嘛?要去做一些增强(通知),前置通知、后置通知、异常通知、最终通知、环绕通知。

切面(Aspect):

切入点和通知的结合

总结以上术语的图:

AOP开发明确事项:

  1. 编写核心业务代码(目标类的目标方法)切入点。

  2. 把公用代码抽取出来 ,制作成通知(增强功能方法)通知。

  3. 在配置文件中,声明切入点与通知间的关系,即切面。

导入AOP相关坐标:

XML 复制代码
<!-- aspectj的织入(切点表达式需要用到该jar包) -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.13</version>
</dependency>

创建目标接口和目标实现类:

java 复制代码
public interface AccountService {
    /* 目标方法: 切入点 要进行拦截的方法 */
    public void transfer();
}
java 复制代码
public class AccountServiceImpl implements AccountService {

    /*要切入的方法*/
    @Override
    public void transfer() {
        System.out.println("this is transfer method");
    }
}

创建通知类:

这个类里面写的就是具体怎么去增强对象

java 复制代码
public class MyAdvice {

    /**
     * 前置通知
     */
    public void before() {
        System.out.println("before advice");
    }

    /**
     * 后置通知
     */
    public void after() {
        System.out.println("after advice");
    }

}

将目标类和通知类对象创建权交给spring:

XML 复制代码
    <!--目标类交给IOC容器-->
    <bean id="accountService" class="com.findyou.service.Impl.AccountServiceImpl"></bean>

    <!--通知类交给IOC容器-->
    <bean id="myAdvice" class="com.findyou.advice.Myadvice"></bean>

xml里面的aop配置:

xml里面的aop配置,用的是**<aop:config>。**

里面写你写好的通知类,也就是你要用哪个类去增强我的对象,用ref去引入,前提是你已经把这个类放到ioc容器里面了。用的标签是**<aop:aspect ret = "">。**

在这个基础上再进行续写,这个通知类里面有很多的方法啊,你要说出来,哪一个是前置通知,哪一个是后置通知等等。前置通知也即是执行原方法之前要做的事情。前置通知的标签是**<aop:before>**, 里面的参数有 method = "类里面的哪个方法", pointcut= "你要限制谁,增强谁",可以理解为:当我触发pointcut里面的方法的时候之前就回去执行 method里面的方法。

无论是 前置通知和后置通知,里面都要有个属性:pointcut , point里面写的就是下面要讲的 切点表达式。如果这个要经常去写的话,可以把pointcut给提取出来。用的时候把之前的pointcut属性改为 pointcut-ref = "提取出来的pointcutId";

XML 复制代码
<aop:pointcut id="myPointcut" expression="execution(* com.findyou.service.Impl.AccountServiceImpl.*(..))" />

切点表达式:

execution(修饰符 返回值类型 包名.类名.方法名(参数))

  • 访问修饰符可以省略
  • 返回值类型、包名、类名、方法名可以使用星号 * 代替,代表任意
  • 包名与类名之间一个点 . 代表当前包下的类,两个点 .. 表示当前包及其子包下的类
  • 参数列表可以使用两个点 .. 表示任意个数,任意类型的参数列表。

当然最常用的也还是: * com.findyou.service.Impl.AccountServiceImpl.* 这样的格式。

总的xml配置文件是:

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:context="http://www.springframework.org/schema/context"
       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
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd">

    <!--目标类交给IOC容器-->
    <bean id="accountService" class="com.findyou.service.Impl.AccountServiceImpl"></bean>

    <!--通知类交给IOC容器-->
    <bean id="myAdvice" class="com.findyou.advice.Myadvice"></bean>

    <!-- AOP配置 -->
    <aop:config>
        <!--execution 翻译为 执行-->
        <!-- 定义切点与通知 -->
        <aop:aspect ref="myAdvice">

            <!-- 切点表达式,指定在哪些方法执行前后添加通知 -->
            <aop:pointcut id="myPointcut" expression="execution(* com.findyou.service.Impl.AccountServiceImpl.*(..))" />
            <!-- 将通知应用于切点 配置的是前置通知 -->
            <aop:before method="before" pointcut = "execution(public void com.findyou.service.Impl.AccountServiceImpl.transfer())"/>
            <aop:after-returning method="after" pointcut-ref="myPointcut"/>
        </aop:aspect>

    </aop:config>


</beans>

测试代码:

java 复制代码
package com.findyou;

import com.findyou.service.AccountService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * @Title: MyTest
 * @Author FindYou
 * @Package com.findyou
 * @Date 2024/12/5 上午11:17
 * @description: 测试类
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class MyTest {

    @Autowired
    private AccountService accountService;

    @Test
    public void testTransfer() throws Exception {
        accountService.transfer(); // 先去执行的是前置通知
    }
    
}

运行的结果是:

相关推荐
卢锡荣5 小时前
单芯掌控多口互联|乐得瑞 LDR6020 PD3.1 多通道 Type‑C 控制 SOC 芯片
c语言·开发语言
2333!!!!!5 小时前
rocket新手一些常见问题
java·开发语言
yume_sibai5 小时前
02-Rust 所有权与借用深入解析(底层原理 + 借用检查器 + 生命周期 + 内部可变性)
开发语言·后端·rust
xxwxx__5 小时前
深入理解 C++ STL:stack、queue 与 deque 从使用到底层实现全解析
开发语言·c++·算法
Highcharts.js5 小时前
甘特图纵向任务、横向时间显示图表可视化开发|Highcharts甘特图示例
开发语言·前端·javascript·可视化·甘特图·数据可视化·highcharts
骇客野人5 小时前
Springboot 的 配置文件 application.yml 和 bootrap.yml 的由来和作用
java·spring boot·后端
wuminyu5 小时前
JVM锁膨胀与Futex源码解析
java·linux·c语言·jvm·c++
郝学胜-神的一滴5 小时前
C++11 工程级应用 08:Lambda表达式与Tuple元组
开发语言·jvm·c++·python·程序人生·开源
CoderYanger5 小时前
A.每日一题:3622. 判断整除性
java·程序人生·算法·leetcode·面试·职场和发展·蓝桥杯
吴声子夜歌5 小时前
ApacheCommons——commons-lang3(Java 基础语言增强)(二)
java·开发语言·apache