基于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(); // 先去执行的是前置通知
    }
    
}

运行的结果是:

相关推荐
Xiaoweidumpb5 分钟前
tomcat temp临时文件不清空,占用硬盘,jdk字体内存泄漏
java·tomcat
F-2H15 分钟前
C语言:指针3(函数指针与指针函数)
linux·c语言·开发语言·c++
AI人H哥会Java18 分钟前
【Spring】控制反转(IoC)与依赖注入(DI)—IoC容器在系统中的位置
java·开发语言·spring boot·后端·spring
凡人的AI工具箱19 分钟前
每天40分玩转Django:Django表单集
开发语言·数据库·后端·python·缓存·django
不能只会打代码21 分钟前
Java并发编程框架之综合案例—— 分布式日志分析系统(七)
java·开发语言·分布式·java并发框架
自律的kkk22 分钟前
SpringBoot中使用AOP切面编程实现登录拦截
java·spring boot·aop·切面编程·登录拦截
丁总学Java24 分钟前
nohup java -jar productQualification.jar --spring.profiles.active=prod $
java·spring·jar
lfl1832616216026 分钟前
thingsboard 自定义html
java·前端·html
中國移动丶移不动32 分钟前
Java 并发编程:原子类(Atomic Classes)核心技术的深度解析
java·后端
知星小度S1 小时前
今天你学C++了吗?——C++中的模板
开发语言·c++