Spring中Aop及日志通知

简介: Spring中Aop及日志通知

一、Aop介绍

( 1 ) 是什么

AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的一个重要特性。AOP通过将与核心业务逻辑无关的横切关注点(如事务管理、日志记录、安全性检查等)独立出来,从而实现了代码的模块化和重用。

在传统的面向对象编程中,通常通过将功能逻辑嵌入到核心业务逻辑中来实现某些功能。然而,这种方式会导致代码的重复和耦合,使得应用程序的维护和扩展变得困难。

而AOP的思想是将这些横切关注点与核心业务逻辑进行解耦。在Spring框架中,AOP通过切面(Aspect)来实现。切面是一个跨越多个类的模块化单元,它定义了横切关注点的行为。

在Spring中,通过使用AOP,你可以将横切关注点抽象为一个切面,并将其应用到多个类或方法上。当程序执行到被切入的方法时,切面的代码将自动执行,完成预定义的功能。

( 2 ) 作用

AOP在Spring框架中具有以下几个作用:

  • 1. 代码解耦:AOP通过将横切关注点(如日志记录、事务管理、安全性检查等)与核心业务逻辑进行解耦,将这些功能从具体的业务代码中抽离出来。这样可以使业务代码更加清晰和简洁,减少了代码的重复和耦合。
  • 2. 横切关注点的集中处理:通过定义切面,将多个类中的相同横切关注点集中处理。例如,多个方法需要进行日志记录,可以将日志记录的代码逻辑抽取到切面中,将切面应用到需要的方法上。这样,无需在每个方法中重复编写日志记录的代码,提高了代码的重用性和可维护性。
  • 3. 代码重用与维护:AOP可以将横切关注点作为独立的模块进行开发和维护。这些模块可以在多个不同的业务场景中重用,减少了开发和维护的工作量。例如,将事务管理的逻辑抽取为切面,可以应用到不同的方法或类中,实现统一的事务管理,提高了代码的复用性和可维护性。
  • 4. 增强系统功能:通过AOP可以增强系统的功能,如安全性检查、性能监控、缓存管理等。这些非功能性需求可以通过切面的方式统一添加到系统中,而不需要修改核心的业务逻辑。这样可以更灵活地对系统进行功能的增强和定制。
  • 5. 可插拔式框架扩展:AOP可以为框架提供可插拔式的扩展能力。例如,Spring框架本身就使用AOP来实现事务管理、缓存管理等功能。开发人员可以基于Spring的AOP机制,为自己的框架增加新的功能,实现可插拔式的框架扩展。
  • 6. 代码的可测试性:AOP可以使代码更易于进行单元测试和集成测试。通过将横切关注点抽取为切面,可以在测试过程中更方便地对关注点进行模拟或验证。这样可以提高测试的覆盖率和测试代码的可读性。

总而言之,AOP在Spring框架中的作用是通过解耦、集中处理横切关注点、增强系统功能、提供框架扩展能力等方面,使得代码更具重用性、可维护性和灵活性。它使开发人员可以更好地管理非核心功能,提高开发效率和系统的可靠性。

( 3 ) 概念和机制

在Spring框架中,AOP的主要概念和机制包括切面(Aspect)、切点(Pointcut)、通知(Advice)、织入(Weaving)和引入(Introduction)等。

  • 1. 切面(Aspect):切面是横切关注点的模块化单元,它由切点和通知组成。切面定义了在特定切点插入的代码逻辑,即在何处和何时执行通知。
  • 2. 切点(Pointcut):切点用于定义切面将会生效的具体位置。通过切点表达式,可以选择需要被切入的方法或类。例如,通过表达式"execution(* com.example.service.*.*(..))"可以选择所有com.example.service包下的方法。
  • 3. 通知(Advice):通知是切面内部的代码逻辑,它决定了在切点何处执行切面的逻辑。Spring定义了多种通知类型,包括:

 - 前置通知(Before):在切点之前的代码逻辑执行。

 - 后置通知(After):在切点之后的代码逻辑执行(无论目标方法是否发生异常)。

 - 返回通知(After-returning):在切点之后的代码逻辑执行(只有目标方法正常返回时)。

 - 异常通知(After-throwing):在切点之后的代码逻辑执行(只有目标方法发生异常时)。

 - 环绕通知(Around):在切点之前和之后的代码逻辑执行,可以完全控制目标方法的执行。

 - 过滤通知(Filtering advice)是一种特殊类型的通知,它用于过滤切点上要执行的切面逻辑。过滤通知可以控制切面是否应该在特定的条件下执行

  • 4. 织入(Weaving):织入是将切面与目标对象的代码进行整合的过程。在Spring中,有两种织入方式:

  - 编译时织入(Compile-time weaving):在编译阶段,将切面织入目标类的字节码中。
  - 运行时织入(Runtime weaving):在运行时,动态地将切面织入目标对象中。

  • 5. 引入(Introduction):引入是一种特殊的通知类型,它允许为目标对象添加新的方法或属性,而不需要修改目标对象的源码。通过引入,可以在不改变类继承关系的情况下,为目标对象添加额外的功能。
  • 连接点(Joinpoint):程序执行过程中明确的点,如方法的调用,或者异常的抛出.
  • 目标(Target):被通知(被代理)的对象
  • 代理(Proxy):将通知应用到目标对象后创建的对象(代理=目标+通知)
  • 切入点(Pointcut):多个连接点的集合,定义了通知应该应用到那些连接点。
  • 适配器(Advisor):适配器=通知(Advice)+切入点(Pointcut)

总结小知识 :

以上这些概念和机制一起协作,通过配置来实现AOP的功能。在Spring中,通过使用XML配置、注解或Java配置来定义切面、切点、通知等,并将切面应用到目标对象上。Spring框架在运行时会自动识别切点,并按照配置的通知类型执行切面的逻辑。

总而言之,Spring框架的AOP通过切面、切点、通知等概念和机制,提供了一种机制来管理横切关注点的代码逻辑。这使得开发人员能够在不修改核心业务逻辑的情况下,实现横切关注点的复用和集中处理,提高了代码的模块化、重用性和可维护性。

 ( 4 ) 特点

AOP(Aspect-Oriented Programming)是一种编程范式,具有以下几个特点:

  • 1. 横切关注点:AOP通过横切关注点的概念,将与核心业务逻辑无关的横切功能(如日志记录、事务管理、安全性检查等)从业务代码中分离出来,形成独立的模块。这样可以实现功能的重用和集中管理,减少了代码冗余和耦合。
  • 2. 切面模块化:AOP将横切关注点抽象为切面,切面是横切关注点的模块化单元,它包含了切点和通知。切点表示切面将会生效的具体位置,而通知表示在切点处执行的代码逻辑。通过切面的定义和组织,可以更好地管理横切关注点,并灵活地将切面应用到不同的目标对象上。
  • 3. 代码解耦和重用:AOP的一个主要目标是解耦,通过将横切关注点与核心业务逻辑进行解耦,可以减少代码间的耦合度。切面可以在多个类和方法中复用,使得横切功能可以统一管理和维护。这样可以提高代码的重用性,减少代码的冗余,同时也使得业务逻辑更加清晰和简洁。
  • 4. 面向切面编程:AOP是一种面向切面的编程范式,它允许开发人员通过定义切面来增强系统功能,而无需修改核心业务逻辑。通过切面的织入,可以在不修改原有代码的情况下,实现对系统的功能增强和定制。
  • 5. 运行时动态代理:AOP通常在运行时对目标对象进行动态代理,即在程序运行时动态地将切面的逻辑织入到目标对象中。这样可以灵活地控制切面的应用范围,并在运行时根据需要进行切换。Spring框架通过动态代理技术实现AOP,提供了对JDK动态代理和CGLIB动态代理的支持。
  • 6. 增强系统功能:AOP可以为系统增加额外的功能,如安全性检查、性能监控、缓存管理等。这些功能可以作为切面的通知部分,通过配置的方式将其应用到目标对象上。通过AOP的方式增强系统功能,不仅可以避免在每个方法中重复编写这些功能逻辑,而且还可以将其与核心业务逻辑分离,提高了代码的可维护性和可测试性。

总而言之,AOP在软件开发中具有横切关注点、切面模块化、代码解耦和重用、面向切面编程、运行时动态代理以及增强系统功能等特点。它能够提高代码的模块化程度、可维护性和灵活性,帮助开发人员更好地管理和扩展横切关注点的代码逻辑。

二、日志通知

首先根据以下项目结构创建项目的接口,类,配置文件(可以根据自己的习惯进行更改)

 IBookBiz 接口

package com.CloudJun.aop.biz.impl;
/**
 * @author CloudJun
 * @create  2023-08-17 14:20
 */
public interface IBookBiz {
    // 购书
    public boolean buy(String userName, String bookName, Double price);
    // 发表书评
    public void comment(String userName, String comments);
}

在exception包内创建一个PriceException的一次类

package com.CloudJun.aop.exception;
/**
 * @author CloudJun
 * @create  2023-08-17 14:26
 * 异常类
 */
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);
  }
}

BookBizImpl 接口实现类

package com.CloudJun.aop.biz.impl;
import com.CloudJun.aop.exception.PriceException;
/**
 * @author CloudJun
 * @create  2023-08-17 14:22
 */
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);
    }
}

spring-aop.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--目标对象-->
    <bean class="com.CloudJun.aop.biz.impl.BookBizImpl" id="bookBiz"></bean>
<!--   通知-->
    <bean class="com.CloudJun.aop.advice.MyMethodBeforeAdvice" id="myMethodBeforeAdvice"></bean>
<!--    代理-->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="proxyFactoryBean" >
</beans>

创建完以接口及类后可能还会出现方法报错及导包报错,查看了项目结构对比导包确实没有问题的情况下,进行以下操作方可恢复:

选中 File 在 点击Settings 查询Java Compiler后选中,如图操作:

Demo 测试类 (测试类中字符串纯属为了搞笑,没有其他意思,嘿嘿嘿。。。)

package com.CloudJun.aop.demo;
import com.CloudJun.aop.biz.impl.IBookBiz;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * @author CloudJun
 * @create  2023-08-17 14:26
 */
public class Demo {
    public static void main(String[] args) {
        //加载spring核心配置文件(建模),获取spring上下文对象及上下文对象中可以获取任何javabean的对象
        ClassPathXmlApplicationContext context  =  new ClassPathXmlApplicationContext("/spring-aop.xml");
        IBookBiz bookBiz = (IBookBiz) context.getBean("bookBiz");
        bookBiz.buy("坤坤","金鸡读立图",19.9);
        bookBiz.comment("坤坤","让我看出坤拳");
    }
}

测 试 结 果  :

( 1 ) 前置通知

要进行前置通知,在advice包内创建一个 MyMethodBeforeAdvice 前置通知类

package com.CloudJun.aop.advice;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.springframework.aop.MethodBeforeAdvice;
/**
 * 买书、评论前加系统日志
 * @author CloudJun
 */
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+")被调用了");
  }
}

在将配置文件修改为以下代码 ( spring-aop.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--目标对象-->
    <bean class="com.CloudJun.aop.biz.impl.BookBizImpl" id="bookBiz"></bean>
<!--   通知-->
    <bean class="com.CloudJun.aop.advice.MyMethodBeforeAdvice" id="myMethodBeforeAdvice"></bean>
<!--    代理-->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="proxyFactoryBean" >
<!--       配置目标对象-->
        <property name="target" ref="bookBiz"></property>
<!--        配置代理的接口,目标对象的接口-->
        <property name="proxyInterfaces" >
            <list>
                <value>com.CloudJun.aop.biz.impl.IBookBiz</value>
            </list>
        </property>
<!--        配置通知-->
        <property name="interceptorNames">
            <list>
                <value>myMethodBeforeAdvice</value>
            </list>
        </property>
    </bean>
</beans>

在测试类(Demo)中将

IBookBiz bookBiz = (IBookBiz) context.getBean("bookBiz");

这一行代码修改为

IBookBiz bookBiz = (IBookBiz) context.getBean("proxyFactoryBean");

如图:

 

再进行测试,开启服务测试代码,如果如图:

           由图我们可看出在方法前会先执行前置通知(相当于进行了方法调用的记录)

( 2 ) 后置通知

在advice包内创建一个后置通知的类为 MyAfterReturningAdvice 的后置通知类

package com.CloudJun.aop.advice;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.springframework.aop.AfterReturningAdvice;
/**
 * 列如场景:买书返利
 * @author CloudJun
 *
 */
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);
  }
}

再在 spring-aop.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--目标对象-->
    <bean class="com.CloudJun.aop.biz.impl.BookBizImpl" id="bookBiz"></bean>
<!--   通知-->
    <bean class="com.CloudJun.aop.advice.MyMethodBeforeAdvice" id="myMethodBeforeAdvice"></bean><!--前置-->
    <bean class="com.CloudJun.aop.advice.MyAfterReturningAdvice" id="myAfterReturningAdvice"></bean><!--后置-->
<!--    代理-->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="proxyFactoryBean" >
<!--       配置目标对象-->
        <property name="target" ref="bookBiz"></property>
<!--        配置代理的接口,目标对象的接口-->
        <property name="proxyInterfaces" >
            <list>
                <value>com.CloudJun.aop.biz.impl.IBookBiz</value>
            </list>
        </property>
        <!--配置通知-->
        <property name="interceptorNames">
            <list>
                <!--前置-->
                <value>myMethodBeforeAdvice</value>
                <!--后置-->
                <value>myAfterReturningAdvice</value>
            </list>
        </property>
    </bean>
</beans>

进行测试,结果为:

 

          由图可以看出在调用方法后会执行后置通知(相当于进行了方法后的调用的记录)

( 3 ) 环绕通知

advice包内创建一个环绕通知的类为 MyMethodInterceptor 的环绕通知类

package com.CloudJun.aop.advice;
import java.util.Arrays;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/**
 * 环绕通知
 *  包含了前置和后置通知
 * @author CloudJun
 *
 */
public class MyMethodInterceptor implements MethodInterceptor {
  @Override
  public Object invoke(MethodInvocation arg0) throws Throwable {
    String target = arg0.getThis().getClass().getName();
    String methodName = arg0.getMethod().getName();
    String args = Arrays.toString(arg0.getArguments());
    System.out.println("【环绕通知调用前:】:"+target+"."+methodName+"("+args+")被调用了");
//    arg0.proceed()就是目标对象的方法
    Object proceed = arg0.proceed();
    System.out.println("【环绕通知调用后:】:该方法被调用后的返回值为:"+proceed);
    return proceed;
  }
}

再在 spring-aop.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--目标对象-->
    <bean class="com.CloudJun.aop.biz.impl.BookBizImpl" id="bookBiz"></bean>
<!--   通知-->
    <bean class="com.CloudJun.aop.advice.MyMethodBeforeAdvice" id="myMethodBeforeAdvice"></bean><!--前置-->
    <bean class="com.CloudJun.aop.advice.MyAfterReturningAdvice" id="myAfterReturningAdvice"></bean><!--后置-->
    <bean class="com.CloudJun.aop.advice.MyMethodInterceptor" id="methodInterceptor"></bean><!--环绕-->
<!--    代理-->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="proxyFactoryBean" >
<!--       配置目标对象-->
        <property name="target" ref="bookBiz"></property>
<!--        配置代理的接口,目标对象的接口-->
        <property name="proxyInterfaces" >
            <list>
                <value>com.CloudJun.aop.biz.impl.IBookBiz</value>
            </list>
        </property>
        <!--配置通知-->
        <property name="interceptorNames">
            <list>
                <!--前置-->
                <value>myMethodBeforeAdvice</value>
                <!--后置-->
                <value>myAfterReturningAdvice</value>
                <!--环绕-->
                <value>methodInterceptor</value>
            </list>
        </property>
    </bean>
</beans>

进行测试,结果为:

由图可以看出在调用方法前后(环绕)都会执行环绕通知(相当于进行了方法前后的调用的记录)

( 4 ) 异常通知

advice包内创建一个环绕通知的类为 MyThrowsAdvice 的异常通知类

package com.CloudJun.aop.advice;
import com.CloudJun.aop.exception.PriceException;
import org.springframework.aop.ThrowsAdvice;
/**
 * 出现异常执行系统提示,然后进行处理。价格异常为例
 * @author CloudJun
 *
 */
public class MyThrowsAdvice implements ThrowsAdvice {
  public void afterThrowing(PriceException ex) {
    System.out.println("【异常通知】:当价格发生异常,那么执行此处代码块!!!");
  }
}

注意 : 在改通知类中  afterThrowing 方法名称是不能修改的,必须是方法名为afterThrowing

再在 spring-aop.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--目标对象-->
    <bean class="com.CloudJun.aop.biz.impl.BookBizImpl" id="bookBiz"></bean>
<!--   通知-->
    <bean class="com.CloudJun.aop.advice.MyMethodBeforeAdvice" id="myMethodBeforeAdvice"></bean><!--前置-->
    <bean class="com.CloudJun.aop.advice.MyAfterReturningAdvice" id="myAfterReturningAdvice"></bean><!--后置-->
    <bean class="com.CloudJun.aop.advice.MyMethodInterceptor" id="methodInterceptor"></bean><!--环绕-->
    <bean class="com.CloudJun.aop.advice.MyThrowsAdvice" id="myThrowsAdvice"></bean><!--异常-->
<!--    代理-->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="proxyFactoryBean" >
<!--       配置目标对象-->
        <property name="target" ref="bookBiz"></property>
<!--        配置代理的接口,目标对象的接口-->
        <property name="proxyInterfaces" >
            <list>
                <value>com.CloudJun.aop.biz.impl.IBookBiz</value>
            </list>
        </property>
        <!--配置通知-->
        <property name="interceptorNames">
            <list>
                <!--前置-->
                <value>myMethodBeforeAdvice</value>
                <!--后置-->
                <value>myAfterReturningAdvice</value>
                <!--环绕-->
                <value>methodInterceptor</value>
                <!--异常-->
                <value>myThrowsAdvice</value>
            </list>
        </property>
    </bean>
</beans>

为了演示错误,我们将测试类中的bookBiz.buy("坤坤","金鸡读立图",19.9);

修改为

bookBiz.buy("坤坤","金鸡读立图",-19.9);

进行测试,结果为:

 

在执行代码出现异常时给予提示,说明代码的问题所在,还可以在异常类(MyThrowsAdvice )

中的afterThrowing方法里面直接进行异常的处理,让代码执行不进行报错。

( 5 ) 过滤通知

将Demo测试类中的bookBiz.buy("坤坤","金鸡读立图",-19.9);修改回原来的代码。

以下代码:

bookBiz.buy("坤坤","金鸡读立图",19.9);

要求: 后置通知必须要在买完书之后才会出现通知(买书返利)。

只需要修改spring-aop.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--目标对象-->
    <bean class="com.CloudJun.aop.biz.impl.BookBizImpl" id="bookBiz"></bean>
<!--   通知-->
    <bean class="com.CloudJun.aop.advice.MyMethodBeforeAdvice" id="myMethodBeforeAdvice"></bean><!--前置-->
    <bean class="com.CloudJun.aop.advice.MyAfterReturningAdvice" id="myAfterReturningAdvice"></bean><!--后置-->
    <bean class="com.CloudJun.aop.advice.MyMethodInterceptor" id="methodInterceptor"></bean><!--环绕-->
    <bean class="com.CloudJun.aop.advice.MyThrowsAdvice" id="myThrowsAdvice"></bean><!--异常-->
    <bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="advisor">
        <!--过滤后置通知 ref内填写需要过滤的配置通知ID-->
        <property name="advice" ref="myAfterReturningAdvice"></property>
        <!--value是过滤的方法-->
        <property name="pattern" value=".*buy"></property>
    </bean>
<!--    代理-->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="proxyFactoryBean" >
<!--       配置目标对象-->
        <property name="target" ref="bookBiz"></property>
<!--        配置代理的接口,目标对象的接口-->
        <property name="proxyInterfaces" >
            <list>
                <value>com.CloudJun.aop.biz.impl.IBookBiz</value>
            </list>
        </property>
        <!--配置通知-->
        <property name="interceptorNames">
            <list>
                <!--前置-->
                <value>myMethodBeforeAdvice</value>
<!--                &lt;!&ndash;后置&ndash;&gt;-->
<!--                <value>myAfterReturningAdvice</value>-->
                <!--过滤-->
                <value>advisor</value>
                <!--环绕-->
                <value>methodInterceptor</value>
                <!--异常-->
                <value>myThrowsAdvice</value>
            </list>
        </property>
    </bean>
</beans>

进行测试,结果为:

 

由图中可以看出只有买书的方法有后置通知(买书返利)

而给书的评论的方法就没有后置通知(买书返利)

说明已经进行了筛选

给我们带来收获

学习Spring中的AOP(面向切面编程)可以带来以下收获:

  1. 模块化:AOP允许将横切关注点(例如日志记录、事务管理等)从核心业务逻辑中分离出来,将其作为一个独立的模块进行开发和维护。这样可以提高代码的可读性和可维护性,使系统更加模块化和灵活。
  2. 代码重用:AOP通过将通用的横切关注点抽象为切面,并将其应用到多个不同的类和模块中,可以实现代码的重用。这样可以减少重复的代码编写,提高开发效率。
  3. 面向横切关注点编程:AOP将关注点从传统的面向对象编程的纵向结构转变为横向结构,使得系统的结构更加清晰。通过将横切关注点抽象为切面,可以将其应用到系统的多个模块中,提高系统的可扩展性和可维护性。
  4. 提高系统的性能:AOP可以在运行时动态地将切面织入到目标对象中,从而实现对目标对象的增强。例如,可以通过AOP实现缓存、事务管理等功能,从而提高系统的性能和可靠性。
  5. 实现安全性控制:AOP可以用于实现安全性控制,通过在切面中定义安全性的规则和权限检查,可以对系统的访问进行控制。这样可以提高系统的安全性,防止未授权的访问和恶意操作。
  6. 日志记录和调试:AOP可以用于实现日志记录和调试功能,通过在切面中定义日志记录的规则和操作,可以自动记录系统的运行日志和调试信息。这样可以方便排查和解决问题,提高系统的可靠性和可维护性。
  7. 提供性能监控:AOP可以用于实现性能监控,通过在切面中定义性能监控的规则和操作,可以自动收集系统的性能数据和指标。这样可以及时发现和解决性能问题,提高系统的性能和响应能力。

总结来说,学习Spring中的AOP可以帮助我们解耦业务逻辑、提供声明式事务管理、实现安全性控制、日志记录和调试以及性能监控等功能。这些收获可以提高系统的可维护性、可测试性、安全性和性能,使我们的开发工作更加高效和稳定。

                                       

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
4天前
|
运维 Java 程序员
Spring5深入浅出篇:基于注解实现的AOP
# Spring5 AOP 深入理解:注解实现 本文介绍了基于注解的AOP编程步骤,包括原始对象、额外功能、切点和组装切面。步骤1-3旨在构建切面,与传统AOP相似。示例代码展示了如何使用`@Around`定义切面和执行逻辑。配置中,通过`@Aspect`和`@Around`注解定义切点,并在Spring配置中启用AOP自动代理。 进一步讨论了切点复用,避免重复代码以提高代码维护性。通过`@Pointcut`定义通用切点表达式,然后在多个通知中引用。此外,解释了AOP底层实现的两种动态代理方式:JDK动态代理和Cglib字节码增强,默认使用JDK,可通过配置切换到Cglib
|
2天前
|
设计模式 数据采集 监控
Spring日志框架
Spring日志框架
6 0
|
4天前
|
XML Java 数据格式
Spring使用AOP 的其他方式
Spring使用AOP 的其他方式
14 2
|
4天前
|
XML Java 数据格式
Spring 项目如何使用AOP
Spring 项目如何使用AOP
18 2
|
9天前
|
Java 开发者 Spring
Spring AOP的切点是通过使用AspectJ的切点表达式语言来定义的。
【5月更文挑战第1天】Spring AOP的切点是通过使用AspectJ的切点表达式语言来定义的。
22 5
|
9天前
|
XML Java 数据格式
Spring AOP
【5月更文挑战第1天】Spring AOP
25 5
|
10天前
|
Java 编译器 开发者
Spring的AOP理解
Spring的AOP理解
|
10天前
|
XML Java 数据格式
如何在Spring AOP中定义和应用通知?
【4月更文挑战第30天】如何在Spring AOP中定义和应用通知?
16 0
|
10天前
|
安全 Java 开发者
在Spring框架中,IoC和AOP是如何实现的?
【4月更文挑战第30天】在Spring框架中,IoC和AOP是如何实现的?
21 0
|
11天前
|
缓存 监控 Java
【Spring系列笔记】AOP
面向切面编程就是面向特定方法编程。通过将横切关注点(cross-cutting concerns)从主要业务逻辑中分离出来,提供一种更好的代码模块化和可维护性。 横切关注点指的是在应用程序中横跨多个模块或层的功能,例如日志记录、事务管理、安全性、缓存、异常处理等。
24 0