首页 > 编程语言 > 详细

Spring:七、AOP

时间:2021-08-06 10:42:59      阅读:25      评论:0      收藏:0      [点我收藏+]

10、AOP

学习Spring AOP之前,先了解一下AOP的底层实现:代理模式

10.1、简介

AOP(Aspect-oriented Programming):面向切面编程,是Spring的关键组件之一。

通过预编译方式和运行时动态代理实现程序功能的统一维护。

  1. AOP 是对 OOP 的补充(Object-oriented Programming,面向对象编程);
  2. OOP 中模块化的单位是类(Class),AOP 中模块化的单位是切面(Aspect);
  3. 切面能够实现跨类型和跨对象的横切关注点(如事务管理)的模块化;
  4. Spring IoC 容器不依赖于AOP,但 AOP 对 Spring IoC 进行了补充,提供了一个强大的中间件解决方案。

技术分享图片

10.2、Spring AOP

10.2.1、作用

AOP 在 Spring 框架中的作用:

  • 提供声明式企业服务,最重要的是声明式事务管理
  • 允许用户自定义切面,使用AOP来补充OOP。

10.2.2、术语

  • 目标对象(Target object:被通知的对象,也称为通知对象;

  • 连接点(Join point:程序执行过程中的一个点,是目标对象的一个方法或异常处理;

  • 横切关注点:跨越多个类的方法或功能。即与业务逻辑无关,但是需要关注的部分(如安全、日志、缓存、事务等);

  • 切面(Aspect:横切关注点的模块化,是一个

  • 通知(Advice:切面在连接点采取的行动,它是类的一个方法

  • 切入点(Pointcut:匹配连接点,是通知执行的 ”地点“;

  • AOP 代理(AOP proxy)**:AOP 创建的对象,用于执行通知的方法等;

  • 编织(Weaving:将切面与其他应用程序或对象联系起来,以创建目标对象,在运行时执行。

Advice 类型:

通知类型 执行点 实现接口
前置通知(Before 连接点之前(方法前) org.springframework.aop.MethodBeforeAdvice
后置通知(After / Finally 连接点之后(方法后) org.springframework.aop.AfterAdvice
返回后通知(After returning 连接点正常完成后(方法后) org.springframework.aop.AfterReturningAdvice
环绕通知(Around 环绕连接点(方法前) org.springframework.aop.aspectj.AspectJAroundAdvice
抛出后通知(After throwing 方法抛出异常 org.springframework.aop.ThrowsAdvice

10.3、实现AOP

需求:为 CRUD操作添加通知(前、后)。

10.3.1、搭建环境

1、导入依赖、引入信息

导入编织依赖

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.7</version>
    <scope>runtime</scope>
</dependency>

引入 Spring 配置信息

xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd"

2、接口和实现类

public interface UserService {
    /**
     * 增加
     */
    void insert();

    /**
     * 删除
     */
    void delete();

    /**
     * 更新
     */
    void update();

    /**
     * 查询
     */
    void query();
}

public class UserServiceImpl implements UserService {
    @Override
    public void insert() {
        System.out.println("----增加一个用户----");
    }

    @Override
    public void delete() {
        System.out.println("----删除一个用户----");
    }

    @Override
    public void update() {
        System.out.println("----更新一个用户----");
    }

    @Override
    public void query() {
        System.out.println("----查询一个用户----");
    }
}

3、通知

public class LogAfterReturningAdvice implements AfterReturningAdvice {
    /**
     * 后置通知
     *
     * @param returnValue 方法的返回值
     * @param method      目标对象的方法
     * @param args        参数
     * @param target      目标对象
     * @throws Throwable
     */
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("返回后通知:"
                + target.getClass().getName()
                + "的" + method.getName()
                + "方法被执行了,返回值为"
                + returnValue);
    }
}

10.3.1、Spring API接口实现

配置AOP

applicationContext.xml

切入点

  • expression表达式:权限修饰符 返回值类型 类名.方法名 方法参数
    • *:代表通配,即所有权限修饰符、所有返回值类型、所有方法...
    • (..):代表任何方法参数
  • advisor通知:
    • advice-ref:引用通知
    • pointcut-ref:引用切入点。
<?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
       https://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="userService" class="indi.jaywee.service.UserServiceImpl"/>
    <bean id="logAfterReturning" class="indi.jaywee.Utils.LogAfterReturningAdvice"/>

    <!-- 配置AOP -->
    <aop:config>
        <!-- 切入点 -->
        <aop:pointcut id="pointcut" expression="execution(* indi.jaywee.service.UserServiceImpl.* (..))"/>

        <!-- 通知 -->
        <aop:advisor advice-ref="logAfterReturning" pointcut-ref="pointcut"/>

    </aop:config>

</beans>

测试

注意:

  1. AOP的底层实现是动态代理,因此获得的Bean对象是代理对象,而不是已写好的实现类;
  2. XML 中注册的是接口实现类,获得的 Bean 对象是接口的代理对象。
@Test
public void test() {
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

    // 错误写法:
    // UserService userService = context.getBean("userService", userServiceImpl.class);


    // 正确写法
    UserService userService = context.getBean("userService", UserService.class);
    // 另一种正确写法
    // UserService userService = (userService) context.getBean("userService");

    userService.insert();
    userService.delete();
    userService.update();
    userService.query();
}

理解

技术分享图片

简单理解如下:

  1. 目标对象:我们要使用AOP的对象,如UserService;
  2. 连接点:目标对象中原有的方法,要在这个方法周围添加功能
  3. 横切关注点:要在目标对象的哪个点加入功能(抽象概念);
  4. 切面:一个类,声明了要添加到目标对象的方法;
  5. 通知:要添加到目标对象的方法;
  6. 切入点:对应连接点,要添加到目标对象的方法的执行位置。

Spring:七、AOP

原文:https://www.cnblogs.com/secretmrj/p/15106653.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!