基于XML的AOP开发

发布于:2024-12-07 ⋅ 阅读:(96) ⋅ 点赞:(0)

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

AOP相关术语:

目标对象(Target):

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

代理对象(Proxy):

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

连接点(Joinpoint):

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

切入点(Pointcut):

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

通知/增强(Advice):

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

切面(Aspect):

切入点和通知的结合

总结以上术语的图:

AOP开发明确事项:

1. 编写核心业务代码(目标类的目标方法)切入点。
2. 把公用代码抽取出来,制作成通知(增强功能方法)通知。
3. 在配置文件中,声明切入点与通知间的关系,即切面。

导入AOP相关坐标:

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

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

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

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

创建通知类:

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

public class MyAdvice {

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

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

}

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

    <!--目标类交给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";

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

切点表达式:

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

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

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

总的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>

测试代码:

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

运行的结果是:
 


网站公告

今日签到

点亮在社区的每一天
去签到