Spring系列篇--关于AOP【面向切面】的详解

这篇具有很好参考价值的文章主要介绍了Spring系列篇--关于AOP【面向切面】的详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一.AOP是什么

二.案例演示 

1.前置通知1.1 先准备接口

1.2然后再准备好实现类

1.3对我们的目标对象进行JavaBean配置 

1.4 编写前置系统日志通知

1.5配置系统通知XML中的JavaBean

1.6 配置代理XML中的JavaBean

1.7 测试代码开始测试

注意这里有一个报错问题!!!

2. 后置通知2.1 先准备好后置通知的系统日志

2.2 配置后置系统通知的XML的JavaBean

 2.3 测试结果

3.环绕通知

3.2 环绕通知的系统日志

3.3 配置环绕通知的XML的JavaBean与前置通知和后置通知一致

3.4 测试结果

4.异常通知4.1 异常通知的系统日志和其他系统日志不同的是,方法名为固定的afterThrowing,不能修改

5.过滤通知5.1 直接在XML中配置JavaBean

四.总结aop是面向切面编程,普通程序由上而下正常执行,aop的程序执行是先执行到目标对象的目标方法中,如果连接点上由前置通知,则先执行前置通知再执行目标方法,最后如果目标方法有后置通知则最后执行后置通知代码,不管是前置通知,后置通知,环绕通知,异常通知,过滤通知,代码都是非业务核心代码,如日志、事务的管理(开启、提交、回滚)         


一.AOP是什么

简介:
面向切面编程(Aspect-Oriented Programming)是一种编程范式,它的主要目的是通过预编译和运行期动态代理实现程序功能的横切(cross-cutting)特性,如日志记录、性能统计、事务监控等。它可以帮助开发者将这些原本分散在各个方法或类中的业务逻辑抽象出来,提高代码复用性,降低耦合度
AOP(Aspect-Oriented Programming)是Spring框架的一个重要特性,它通过将横切关注点(cross-cutting concerns)从核心业务逻辑中分离出来,以模块化的方式在整个应用程序中重复使用。以下是关于AOP的简介及其特点:

AOP是一种编程范式,它通过将横切关注点切割出来,将其模块化,并将其应用于多个类和模块,以提高代码的重用性和可维护性。
横切关注点是指与核心业务逻辑无关但存在于多个类或模块中的非功能性需求,例如日志记录、性能监控、事务管理等。
特点:

模块化:AOP允许将横切关注点从核心业务逻辑中提取出来,形成独立的切面(Aspect),使得关注点的逻辑可以独立于各个模块。
解耦:AOP通过解耦横切关注点与核心业务逻辑,使得它们可以独立演化和变化,提高了模块之间的松耦合程度。
重用性:AOP允许将切面应用于多个类和模块,从而实现了关注点的重用,避免了代码的重复编写。
可维护性:将横切关注点抽象为切面后,使得代码结构更清晰,易于理解和维护。
动态性:AOP可以在运行时动态地将切面应用到目标对象上,而不需要修改目标对象的源代码,增强了系统的灵活性和可扩展性。
多样性:Spring框架支持不同类型的切面编程,包括基于代理的AOP和基于字节码增强的AOP。这样可以选择最适合应用程序需求的AOP实现方式。
在Spring框架中,AOP的实现采用了代理模式和动态代理技术。Spring提供了多种AOP的实现方式,包括基于XML配置的AOP、基于注解的AOP和基于纯Java配置的AOP(JavaConfig)等,开发者可以根据具体需求选择适合的方式来配置和使用AOP。
 

面向切面:
1.专业术语
①目标对象:
专业解释:被通知(被代理)的对象

通俗理解:在书店中,商品就是目标。每个商品都有自己的属性(比如价格、名称、库存等)和行为(比如计算促销价格、更新库存等)。收银员通过扫描商品的条形码来与商品进行交互,调用商品的方法来获取商品信息以及执行一些操作。商品本身即代表了目标

②连接点:
专业解释:程序执行过程中明确的点,如方法的调用,或者异常的抛出

通俗理解:在书店中,我们可以将顾客结账的行为看作一个连接点

③通知:
专业解释:在某个特定的连接点上执行的动作,同时Advice也是程序代码的具体实现,例如一个实现日志记录的代码(通知有些书上也称为处理)

通俗理解:

前置通知(Before Advice):在切入点前执行的代码,在读者购买图书之前,我们可以记录读者购买的图书信息
后置通知(After Advice):在切入点后执行的代码,在读者购买图书之后,我们可以更新图书库存
环绕通知(Around Advice):在切入点前后都执行的代码,我们可以对读者进行额外的安全检查和记录日志
异常通知(After-Throwing Advice):异常通知是在切入点发生异常时执行的额外功能代码。假设当顾客购买商品的数量大于库存数量时,就会发生异常。我们希望在顾客购买商品时检查库存,并在发生异常时执行异常通知,向顾客显示错误信息并处理异常情况
过滤通知(After-Returning Advice):过滤通知是在切入点成功执行后执行的额外功能代码。假设我们有一个特殊会员组,他们在购买商品时可以获得额外的积分。我们可以使用过滤通知来筛选出这些特殊会员,并在成功购买后给他们添加积分
④代理:
专业解释:将通知应用到目标对象后创建的对象(代理=目标+通知)

通俗理解:在书店中,收银员是一个代理角色。他们既代表顾客与商品交互,又代表书店执行一些额外的任务。当顾客带着商品到收银台时,收银员会扫描每个商品的条形码,获取商品信息并计算总价。这里,收银员即充当了顾客与商品之间的代理角色,也充当了超市执行计算总价等额外任务的代理角色

⑤切入点:
专业解释:

多个连接点的集合,定义了通知应该应用到那些连接点 (也将Pointcut理解成一个条件 ,此条件决定了容器在什么情况下将通知和目标组合成代理返回给外部程序)

通俗理解:在书店场景中,我们可能希望在计算折扣方法之前或之后记录日志和进行库存管理。这些切入点决定了我们在代码中操作的位置

⑥适配器:
专业解释:适配器是一个中间组件,用于将面向切面编程框架与原始的业务逻辑代码连接起来(适配器=通知(Advice)+切入点(Pointcut))

通俗理解:在书店场景中,适配器可以将代理对象与书店的购买图书业务逻辑连接起来,使得代理对象能够在购买图书的过程中添加额外的功能

2.代码演示
        在上面场景模拟的代码中,我们能够发现记录日志的代码基本相同,那么有没有可能将这部分的代码抽取出来进行封装,统一进行维护呢?同时也可以将日志代码和业务代码完全分离,解耦合

  那么我们便可以将业务方法中的非业务核心代码(日志记录)抽离出来形成一个横切面,并且将这个横切面封装成一个对象,将所有的记录日志的代码写到这个对象中,以实现与业务代码的分离,这便是面向切面编程的思想

2.1将记录日志的代码进行封装
 

三.案例演示 

1.前置通知 1.1 先准备接口

package com.lya.aop.biz;
 
public interface IBookBiz {
    // 购书
    public boolean buy(String userName, String bookName, Double price);
 
    // 发表书评
    public void comment(String userName, String comments);
}

1.2然后再准备好实现类

package com.lya.aop.biz.impl;
 
import com.YU.aop.biz.IBookBiz;
import com.YU.aop.exception.PriceException;
 
public class BookBizImpl implements IBookBiz {
 
    public BookBizImpl() {
        super();
    }
 
    public boolean buy(String userName, String bookName, Double price) {
        // 通过控制台的输出方式模拟购书
        if (null == price || price <= 0) {
            throw new PriceException("book price exception");
        }
        System.out.println(userName + " buy " + bookName + ", spend " + price);
        return true;
    }
 
    public void comment(String userName, String comments) {
        // 通过控制台的输出方式模拟发表书评
        System.out.println(userName + " say:" + comments);
    }
 
}

1.3对我们的目标对象进行JavaBean配置 

<!--目标对象-->
    <bean class="com.lya.aop.biz.impl.BookBizImpl" id="bookBiz"></bean>

1.4 编写前置系统日志通知

package com.lya.aop.advice;
 
import java.lang.reflect.Method;
import java.util.Arrays;
 
import org.springframework.aop.MethodBeforeAdvice;
 
/**
 * 买书、评论前加系统日志
 * @author YU
 *
 */
public class MyMethodBeforeAdvice implements MethodBeforeAdvice {
 
    @Override
    public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
//        在这里,可以获取到目标类的全路径及方法及方法参数,然后就可以将他们写到日志表里去
        String target = arg2.getClass().getName();
        String methodName = arg0.getName();
        String args = Arrays.toString(arg1);
        System.out.println("【前置通知:系统日志】:"+target+"."+methodName+"("+args+")被调用了");
    }
 
}

1.5配置系统通知XML中的JavaBean

<!--通知-->
    <bean class="com.lya.aop.advice.MyMethodBeforeAdvice" id="myMethodBeforeAdvice"></bean>

1.6 配置代理XML中的JavaBean

<!-- 代理-->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="bookProxy">
        <!-- 配置目标对象 -->
        <property name="target" ref="bookBiz"></property>
        <!-- 配置代理接口,目标对象的接口 -->
        <property name="proxyInterfaces">
            <value>com.YU.aop.biz.IBookBiz</value>
        </property>
        <property name="interceptorNames">
            <list>
                <value>myMethodBeforeAdvice</value>
            </list>
        </property>
    </bean>

1.7 测试代码开始测试

package com.lya.util;

import com.lya.biz.IBookBiz;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 程序猿-小李哥
 * @site www.xiaolige.com
 * @company 猪八戒有限集团
 * @create 2023-08-17-15:34
 */
public class Demo {
    public static void main(String[] args) {
//        今天所学:
//        1.AOP的介绍:专心做事

//       2专业术语
//        1.连接点
//        2.通知:前,后,环绕
//        3.目标
//        4.代理
//        代理=目标+通知

//        3配置xml初始化Spring容器IOC
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("spring.xml");

//        演示一:目标对象
//        BookBizImpl bookBiz = context.getBean("bookTarget",BookBizImpl.class);
//        bookBiz.buy("晓东","欠你一夜",2000d);
//        bookBiz.comment("晓东","不看亏了,看了真爽啊!");

//        演示二:前置通知
//        错误:类型强转,
        Object proxy1 = context.getBean("proxy");
        System.out.println(proxy1.getClass()+"代理的类型");
//      com.sun.proxy.$Proxy5代理的类型

//      这里proxy==new bookbizimpl
//        BookBizImpl proxy = context.getBean("proxy",BookBizImpl.class);
//        proxy.buy("晓东","欠你一夜",2000d);
//        proxy.comment("晓东","不看亏了,看了真爽啊!");

//        使用接口接收代理对象!!!因为代理对象实现了接口在xml中
        IBookBiz proxy = context.getBean("proxy",IBookBiz.class);
        proxy.buy("晓东","欠你一夜",2000d);
        proxy.comment("晓东","不看亏了,看了真爽啊!");

    }
}

注意这里有一个报错问题!!!

Spring系列篇--关于AOP【面向切面】的详解,初学,Java,spring,mysql,java

因为proxy代理已经实现了接口可以看作为一个实现类

 使用接口接收代理对象!!!因为代理对象实现了接口在xml中

测试结果:

 由测试结果可得知,不仅获取到了我们的参数,同时根据方法获取到了我们的系统日志,也就是前置通知

Spring系列篇--关于AOP【面向切面】的详解,初学,Java,spring,mysql,java

2. 后置通知 2.1 先准备好后置通知的系统日志

package com.zking.aop.advice;
    
import java.lang.reflect.Method;
import java.util.Arrays;
 
import org.springframework.aop.AfterReturningAdvice;
 
/**
 * 买书返利
 * @author Administrator
 *
 */
public class MyAfterReturningAdvice implements AfterReturningAdvice {
 
    @Override
    public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
        String target = arg3.getClass().getName();
        String methodName = arg1.getName();
        String args = Arrays.toString(arg2);
        System.out.println("【后置通知:买书返利】:"+target+"."+methodName+"("+args+")被调用了,"+"该方法被调用后的返回值为:"+arg0);
    
 
    }
 
}

2.2 配置后置系统通知的XML的JavaBean

<!--后置通知-->
    <bean class="com.YU.aop.advice.MyAfterReturningAdvice" id="myAfterReturningAdvice"></bean>
并在前面已经配置好的代理接口中添加一个value值

 2.3 测试结果

 由测试结果我们可以得知,后置通知永远都在方法执行后才会显示通知,与前置通知不同的是每次前面的方法调用后都会返回一个参数

Spring系列篇--关于AOP【面向切面】的详解,初学,Java,spring,mysql,java

3.环绕通知


3.1 环绕通知就是前置通知和后置通知的结合,在实际应用开发中,我们一般不会单独编写前置通知和后置通知,单独使用前置通知或者后置通知时,我们会使用环绕通知,将里面前置(后置)通知的功能注释,以达到单独使用的目的

3.2 环绕通知的系统日志

package com.lya.advice;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import java.util.Arrays;

/**
 * @author 程序猿-小李哥
 * @site www.xiaolige.com
 * @company 猪八戒有限集团
 * @create 2023-08-17-18:45
 *
 * 环绕通知
 */
public class AroundAdvice  implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        //获取目标对象的执行方法
        String methodName=invocation.getMethod().getName();
        //获取目标对象执行方法的参数
        Object[] params=invocation.getArguments();
        //获取目标对象
        Object target = invocation.getThis();
        System.out.println("[环绕通知] "+target.getClass().getName()+"."+methodName+","
                + "执行的参数:"+ Arrays.toString(params));

        Object returnValue = invocation.proceed(); //放行操作
        System.out.println("[环绕通知] 返回参数等于:"+returnValue);
        return returnValue;
    }
}

3.3 配置环绕通知的XML的JavaBean与前置通知和后置通知一致

3.4 测试结果

Spring系列篇--关于AOP【面向切面】的详解,初学,Java,spring,mysql,java

由测试结果得知,环绕通知就是前置通知和后置通知的结合,优点就是不需要再多次去进行配置及编码,所以就像我们前面所说在实际开发应用中我们一般都会选择使用环绕通知

4.异常通知 4.1 异常通知的系统日志和其他系统日志不同的是,方法名为固定的afterThrowing,不能修改

package com.lya.advice;

/**
 * @author 程序猿-小李哥
 * @site www.xiaolige.com
 * @company 猪八戒有限集团
 * @create 2023-08-17-18:56
 */

import org.springframework.aop.ThrowsAdvice;

/**
 * 异常通知
 */
public class ExceptionAdvice implements ThrowsAdvice {
        public void afterThrowing(PriceException e) {
        System.out.println("[异常通知] 价格异常,撤销订单!");
    }
}

价格异常

package com.lya.advice;

/**
 * @author 程序猿-小李哥
 * @site www.xiaolige.com
 * @company 猪八戒有限集团
 * @create 2023-08-17-19:04
 *
 * 价格异常通知
 */
public class PriceException  extends RuntimeException {
    public PriceException() {
        super();
    }
    public PriceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
    public PriceException(String message, Throwable cause) {
        super(message, cause);
    }
    public PriceException(String message) {
        super(message);
    }
    public PriceException(Throwable cause) {
        super(cause);
    }
}

4.2 在我们正常程序出问题没有去配置异常通知时会出现报错,并且不会执行后面的后置通知,如以下情况

4.3 异常处理配置和前面的配置相同

4.4 当我们配置好异常通知模块时,程序出现异常时会上报日志进行提示

5.过滤通知 5.1 直接在XML中配置JavaBean

<!--过滤通知-->
    <bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="regexpMethodPointcutAdvisor">
        <property name="advice" ref="myAfterReturningAdvice"></property>
        <property name="pattern" value=".*buy"></property>
    </bean>


 

将图中指出部分替换成过滤通知

 测试结果:

Spring系列篇--关于AOP【面向切面】的详解,初学,Java,spring,mysql,java

对比框中内容,在调用过buy方法后进行过滤,第二次调用时不再buy方法而是comment方法 文章来源地址https://www.toymoban.com/news/detail-654778.html

四.总结 aop是面向切面编程,普通程序由上而下正常执行,aop的程序执行是先执行到目标对象的目标方法中,如果连接点上由前置通知,则先执行前置通知再执行目标方法,最后如果目标方法有后置通知则最后执行后置通知代码,不管是前置通知,后置通知,环绕通知,异常通知,过滤通知,代码都是非业务核心代码,如日志、事务的管理(开启、提交、回滚)           

到了这里,关于Spring系列篇--关于AOP【面向切面】的详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Java 初级】Spring核心之面向切面编程(AOP)

    tip:作为程序员一定学习编程之道,一定要对代码的编写有追求,不能实现就完事了。我们应该让自己写的代码更加优雅,即使这会费时费力。 💕💕 推荐: 体系化学习Java(Java面试专题) AOP(面向切面编程)是一种编程范式,用于将横切关注点(如日志记录、性能统计等

    2024年02月04日
    浏览(50)
  • Spring面向切面编程(AOP)

    AOP(Aspect Oriented Programming),即面向切面编程,利用一种称为\\\"横切\\\"的技术,剖开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为\\\"Aspect\\\",即切面。所谓\\\"切面\\\",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装

    2024年02月07日
    浏览(48)
  • Spring AOP:面向切面编程

    在软件开发中,我们经常会遇到一些横切关注点(cross-cutting concerns),如日志记录、事务管理和安全性等。这些关注点不属于特定的模块或类,而是横跨整个应用程序。传统的面向对象编程方法往往会将这些关注点与核心业务逻辑混杂在一起,导致代码的可读性和可维护性下

    2024年02月09日
    浏览(46)
  • Spring-aop面向切面

    1、理解必要的专业术语  先看看上面图,这是我的个人理解。(画的丑,主打真实)         1)Advice,通知/增强:类方法中提出来的共性功能(大白话就是提出来的重复代码)         2)Pointcut,切入点/切点:通知返回的方法         3)连接点:方法         4)织入:

    2023年04月15日
    浏览(94)
  • spring之面向切面:AOP(2)

    学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。各位小伙伴,如果您: 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持,想组团高效学习… 想写博客但无从下手,急需写作干货注入能量… 热爱写作,愿意让自己成为更好

    2024年02月04日
    浏览(47)
  • Spring-AOP(面向切面)

    功能接口 实现类 在含有日志输出的实现类中可以了解到:与核心业务功能没有关系的日志输出加杂在模块中,对核心业务功能有干扰。 思路:解耦 , 将附加功能从业务功能模块中抽取出来 概念 二十三种设计模式中的一种,属于结构型模式,它的作用就是通过提供一个代理

    2024年02月16日
    浏览(42)
  • [SSM]Spring面向切面编程AOP

    目录 十五、面向切面编程AOP 15.1AOP介绍 15.2AOP的七大术语 15.3切点表达式 15.4使用Spring的AOP 15.4.1准备工作 15.4.2基于AspectJ的AOP注解式开发 15.4.3基于XML配置方式的AOP(了解) 15.5AOP的实际案例:事务处理 15.6AOP的实际案例:安全日志 IoC使软件组件松耦合。AOP让你能够捕捉系统中经

    2024年02月15日
    浏览(48)
  • 认识 spring AOP (面向切面编程) - springboot

    本篇介绍什么是spring AOP, AOP的优点,使用场景,spring AOP的组成,简单实现AOP 并 了解它的通知;如有错误,请在评论区指正,让我们一起交流,共同进步! 本文开始 AOP: 面向切面编程,也就是面向某一类编程,对某一类事情进行统一处理; spring AOP: 是实现了AOP这种思想的一

    2024年02月14日
    浏览(50)
  • Spring AOP(面向切面编程)和方法拦截

    Spring AOP(面向切面编程)和方法拦截 Spring是一款广泛使用的Java开发框架,提供了丰富的功能和工具,用于简化企业级应用程序的开发。其中一个重要的特性是面向切面编程(AOP)和方法拦截。本文将介绍Spring AOP和方法拦截的概念、工作原理以及在实际开发中的应用。 在软

    2024年02月05日
    浏览(45)
  • 切面的魔力:解密Spring AOP 面向切面编程

    目录 一、AOP简介 1.1 什么是AOP ? 1.2 什么是面向切面编程 ? 1.3 AOP 的特点 二、 AOP的基本概念解读 2.1 AOP的基本概念 2.2 AOP 概念趣事解读 三、代码情景演示 3.1 编写目标对象(超级英雄们正常的行动) 3.2 编写通知类 3.2.1 前置通知 3.2.2 后置通知 3.2.3 异常通知 3.2.4 环绕通知

    2024年02月11日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包