Spring之面向切面(AOP)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Spring之面向切面(AOP)



前言

在Spring框架中,面向切面编程(Aspect-Oriented Programming,AOP)是一种编程范式,用于增强应用程序的模块化性和可重用性。AOP通过在程序执行过程中动态地将额外的行为织入到代码中,可以解耦和横切系统的关注点。

在传统的面向对象编程中,我们将应用程序的功能和业务逻辑以对象的形式进行封装和组织。然而,在某些情况下,我们需要处理跨多个对象、模块或层的关注点,如日志记录、事务管理、安全性等。这些关注点被称为横切关注点(cross-cutting concerns),它们与应用程序的核心逻辑相交织在一起,导致代码的重复和耦合。

AOP通过引入切面(Aspect)来解决这个问题。切面是横切关注点的模块化封装,它包含了横切关注点的逻辑和代码。在Spring中,切面可以通过使用基于注解或XML配置的方式定义。切面会被织入到应用程序的目标对象中,在目标对象的特定连接点(Join Point)上执行相应的行为。

一、AOP(面向切面)简介(了解AOP)

1. 了解AOP中重要的概念及术语

  1. 切点(Pointcut):切点指定了在应用程序中哪些连接点应该被拦截和处理。连接点可以是方法的执行、方法的调用、对象的创建与初始化等。切点可以使用表达式或模式进行定义,以匹配特定的连接点。
  2. 通知(Advice):通知指定了在切点上要执行的逻辑。通知可以是在切点之前、之后或周围执行。在Spring中,常见的通知类型有前置通知、后置通知、返回通知和异常通知。
  3. 切面(Aspect):切面是通知和切点的组合。它是代码模块化的单元,它封装了特定关注点的逻辑和行为。切面定义了在哪些切点上应该执行特定的通知。
  4. 织入(Weaving):织入是将切面应用到目标对象中的过程。它可以在编译时、类加载时或运行时发生。Spring使用代理织入字节码织入两种主要的织入方式。
  5. 引入(Introduction):引入允许我们向现有的类添加新方法或属性。它允许我们在不修改原始代码的情况下向现有类添加新的行为。

2. AOP的一些关键功能

  • 切面优先级(Aspect Ordering):如果有多个切面应用于同一个切点,可以通过指定优先级来定义它们的执行顺序。
  • 切面的横切关注点条件(Aspect Pointcut Conditions):可以使用条件表达式定义在何时应用切面。这允许我们根据特定的条件选择性地应用切面。
  • 异常处理(Exception Handling):AOP允许我们在方法抛出异常时自动捕获并处理异常。
  • 事务管理(Transaction Management):AOP可以用于实现声明式事务管理,将事务相关的代码从业务逻辑中分离出来,使得代码更加清晰和可维护。

3. AOP的作用领域

AOP的作用领域

领域 说明
日志记录 通过AOP可以实现自动的日志记录,记录方法的调用、参数、返回值等,方便系统的监控和问题排查。
事务管理 AOP可以实现声明式事务管理,将事务处理的代码从业务逻辑中分离出来,使得代码更加简洁和易于维护。
安全性 通过AOP可以实现对系统的安全性进行管理,例如进行身份验证、权限检查等。
缓存管理 AOP可以实现对方法的结果进行缓存,在方法执行前先检查缓存,提高系统的性能和响应速度。
异常处理 通过AOP可以实现统一的异常处理,将异常捕获并进行处理,避免异常的冒泡传播。
性能监控 AOP可以用于对方法执行时间、资源消耗等进行监控和统计,以便进行性能优化和调整。

二、AOP的使用(面向切面)

面向切面工程改变了原有代码块的执行模式,原有代码是从上至下执行代码。而我们面向切面工程是代码从上至下执行,当代码执行到连接点时,如果它有前置通知则先执行前置通知再执行目标对象,因此一个完整的业务链就执行完成了;如果说执行到连接点时,它没有前置对象则先执行目标对象,再看看下面的连接点有没有后置通知,若有则执行后置通知,因此这个完整的业务就完成了。

1. AOP解决的问题

解决了客户项目的需求改变,造成了在原有没必要改变的代码,则需要去改变它原有的代码。例如:在一个图书项目中的书籍管理的增删改的三个功能,本身只需要完成增删改三个功能实现即可,这时如果要求需要添加日志功能,那么需要在原有的代码基础上去修改添加日志功能,则受牵连的方法就三个(add、update、delete)。

2. AOP使用中的关键性概念

  • 连接点(Joinpoint):程序执行过程中明确的点,如方法的调用,或者异常的抛出。
  • 目标(Target):被通知(被代理)的对象。(作用:完成具体的业务逻辑)
  • 通知(Advice):在某个特定的连接点上执行的动作,同时Advice也是程序代码的具体实现,例如一个实现日志记录的代码(通知有些书上也称为处理)  (作用:完成切面编程)
  • 代理(Proxy):将通知应用到目标对象后创建的对象(代理=目标+通知)。
    例子:外科医生+护士。                                                                                                            说明:只有代理对象才有AOP功能,而AOP的代码是写在通知的方法里面的。
  • 切入点(Pointcut):多个连接点集合,定义了通知应该应用到那些连接点。
    (也将Pointcut理解成一个条件 ,此条件决定了容器在什么情况下将通知和目标组合成代理返回给外部程序)

注:可以将切入点看作是连接点的一个集合

  • 适配器(Advisor)适配器=通知(Advice)+切入点(Pointcut)

三、AOP的通知类型及案例测试

1.通知类型

AOP的通知类型

通知类型 说明
前置通知(Before) 在目标方法执行前执行的通知。
后置通知(After) 在目标方法执行后(无论是否抛出异常)执行的通知。
异常通知(After Throwing) 在目标方法抛出异常后执行的通知。
环绕通知(Around) 在目标方法执行前后执行的自定义行为。
过滤通知(Throws Advice) 在目标方法执行前后执行的自定义行为。

案例业务功能部署

IBookBiz接口类

package com.yx.AOP.biz;
public interface IBookBiz {
  // 购书
  public boolean buy(String userName, String bookName, Double price);
  // 发表书评
  public void comment(String userName, String comments);
}
BookBizImpl接口实现类
package com.yx.AOP.biz.Impl;
import com.yx.AOP.biz.IBookBiz;
import com.yx.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);
  } 
}
PriceException价格异常类
package com.yx.AOP.exception;
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);
  }
}
Spring-context.xml配置Bean元素
<?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">
    <!--AOP-->
<!-- 配置目标对象-->
    <bean class="com.yx.AOP.biz.Impl.BookBizImpl" id="bookBiz"></bean>
</beans>
测试类Demo1代码(测试方法)
package com.yx.AOP.Demo;
import com.yx.AOP.biz.IBookBiz;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 * @create  2023-08-17 18:15
 * 测试类
 */
public class Demo1 {
   public static void main(String[] args) {
      ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("Spring-context.xml");
      IBookBiz bookBiz = (IBookBiz) context.getBean("bookBiz");
      bookBiz.buy("木易","斗破苍穹",25d);
      bookBiz.comment("木易","太精彩了!!!");
   }
}
测试输出结果

成功打印出方法内的输出语句,说明案例部署成功没有问题。

注意事项

记得修改配置项目的jdk,要求与自身电脑安装的JKD版本一致,否则有一些的类的方法编写会报错。(步骤如下)

2. 通知案例

2.1 前置通知

MyMethodBeforeAdvice(前置通知类)
package com.zking.aop.advice;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.springframework.aop.MethodBeforeAdvice;
/**
 * 买书、评论前加系统日志
 * @author Administrator
 *
 */
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-context.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">
    <!--AOP-->
<!-- 配置目标对象-->
    <bean class="com.yx.AOP.biz.Impl.BookBizImpl" id="bookBiz"></bean>
<!--    通知-->
<!--    前置通知-->
    <bean class="com.yx.AOP.advice.MyMethodBeforeAdvice" id="methodBeforeAdvice"></bean>
<!--代理-->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="bookProxy">
<!--        配置目标对象-->
        <property name="target" ref="bookBiz"></property>
<!--        配置代理接口,目标对象的接口-->
        <property name="proxyInterfaces">
            <list>
                <value>com.yx.AOP.biz.IBookBiz</value>
            </list>
        </property>
        <!--        配置通知-->
        <property name="interceptorNames">
            <list>
<!--                前置通知-->
                <value>methodBeforeAdvice</value>
            </list>
        </property>
    </bean>
</beans>
测试类代码Demo1
package com.yx.AOP.Demo;
import com.yx.AOP.biz.IBookBiz;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 * @create  2023-08-17 18:15
 * 测试类
 */
public class Demo1 {
   public static void main(String[] args) {
      ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("Spring-context.xml");
//      IBookBiz bookBiz = (IBookBiz) context.getBean("bookBiz");
      IBookBiz bookBiz = (IBookBiz) context.getBean("bookProxy");
      bookBiz.buy("木易","斗破苍穹",25d);
      bookBiz.comment("木易","太精彩了!!!");
   }
}
测试效果

2.2 后置通知

目的:实现买书返利的功能

MyAfterReturningAdvice (后置通知类)
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);
  }
}
Spring-context.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">
    <!--AOP-->
<!-- 配置目标对象-->
    <bean class="com.yx.AOP.biz.Impl.BookBizImpl" id="bookBiz"></bean>
<!--    通知-->
<!--    后置通知-->
    <bean class="com.yx.AOP.advice.MyAfterReturningAdvice" id="myAfterReturningAdvice"></bean>
<!--代理-->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="bookProxy">
<!--        配置目标对象-->
        <property name="target" ref="bookBiz"></property>
<!--        配置代理接口,目标对象的接口-->
        <property name="proxyInterfaces">
            <list>
                <value>com.yx.AOP.biz.IBookBiz</value>
            </list>
        </property>
        <!--        配置通知-->
        <property name="interceptorNames">
            <list>
<!--                后置通知-->
                <value>myAfterReturningAdvice</value>
            </list>
        </property>
    </bean>
</beans>
测试类Demo1代码
package com.yx.AOP.Demo;
import com.yx.AOP.biz.IBookBiz;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 * @create  2023-08-17 18:15
 * 测试类
 */
public class Demo1 {
   public static void main(String[] args) {
      ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("Spring-context.xml");
//      IBookBiz bookBiz = (IBookBiz) context.getBean("bookBiz");
      IBookBiz bookBiz = (IBookBiz) context.getBean("bookProxy");
      bookBiz.buy("木易","斗破苍穹",25d);
      bookBiz.comment("木易","太精彩了!!!");
   }
}
测试输出结果

2.3 环绕通知

MyMethodInterceptor(环绕通知类)
package com.yx.AOP.advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import java.util.Arrays;
/**
 * 环绕通知
 *  包含了前置和后置通知
 * 
 * @author Administrator
 *
 */
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-context.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">
    <!--AOP-->
<!-- 配置目标对象-->
    <bean class="com.yx.AOP.biz.Impl.BookBizImpl" id="bookBiz"></bean>
<!--    通知-->
<!--    环绕通知-->
    <bean class="com.yx.AOP.advice.MyMethodInterceptor" id="methodInterceptor"></bean>
<!--代理-->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="bookProxy">
<!--        配置目标对象-->
        <property name="target" ref="bookBiz"></property>
<!--        配置代理接口,目标对象的接口-->
        <property name="proxyInterfaces">
            <list>
                <value>com.yx.AOP.biz.IBookBiz</value>
            </list>
        </property>
        <!--        配置通知-->
        <property name="interceptorNames">
            <list>
<!--                环绕通知-->
                <value>methodInterceptor</value>
            </list>
        </property>
    </bean>
</beans>
测试类Demo1代码
package com.yx.AOP.Demo;
import com.yx.AOP.biz.IBookBiz;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 * @create  2023-08-17 18:15
 * 测试类
 */
public class Demo1 {
   public static void main(String[] args) {
      ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("Spring-context.xml");
//      IBookBiz bookBiz = (IBookBiz) context.getBean("bookBiz");
      IBookBiz bookBiz = (IBookBiz) context.getBean("bookProxy");
      bookBiz.buy("木易","斗破苍穹",25d);
      bookBiz.comment("木易","太精彩了!!!");
   }
}
测试输出结果

2.4 异常通知

MyThrowsAdvice (异常通知类代码)
package com.yx.AOP.advice;
import com.yx.AOP.exception.PriceException;
import org.springframework.aop.ThrowsAdvice;
/**
 * 出现异常执行系统提示,然后进行处理。价格异常为例
 * @author Administrator
 *异常通知
 */
public class MyThrowsAdvice implements ThrowsAdvice {
  public void afterThrowing(PriceException ex) {
    System.out.println("【异常通知】:当价格发生异常,那么执行此处代码块!!!");
  }
}
Spring-context.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">
    <!--AOP-->
<!-- 配置目标对象-->
    <bean class="com.yx.AOP.biz.Impl.BookBizImpl" id="bookBiz"></bean>
<!--    通知-->
<!--    异常通知-->
    <bean class="com.yx.AOP.advice.MyThrowsAdvice" id="throwsAdvice"></bean>
<!--代理-->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="bookProxy">
<!--        配置目标对象-->
        <property name="target" ref="bookBiz"></property>
<!--        配置代理接口,目标对象的接口-->
        <property name="proxyInterfaces">
            <list>
                <value>com.yx.AOP.biz.IBookBiz</value>
            </list>
        </property>
        <!--        配置通知-->
        <property name="interceptorNames">
            <list>
<!--                异常通知-->
                <value>throwsAdvice</value>
            </list>
        </property>
    </bean>
</beans>
测试类Demo1代码
package com.yx.AOP.Demo;
import com.yx.AOP.biz.IBookBiz;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 * @create  2023-08-17 18:15
 * 测试类
 */
public class Demo1 {
   public static void main(String[] args) {
      ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("Spring-context.xml");
//      IBookBiz bookBiz = (IBookBiz) context.getBean("bookBiz");
      IBookBiz bookBiz = (IBookBiz) context.getBean("bookProxy");
      bookBiz.buy("木易","斗破苍穹",-25d);
      bookBiz.comment("木易","太精彩了!!!");
   }
}
测试输出结果

2.5 过滤通知

Spring-context.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">
    <!--AOP-->
<!-- 配置目标对象-->
    <bean class="com.yx.AOP.biz.Impl.BookBizImpl" id="bookBiz"></bean>
<!--    通知-->
<!--    前置通知-->
    <bean class="com.yx.AOP.advice.MyMethodBeforeAdvice" id="methodBeforeAdvice"></bean>
<!--    后置通知-->
    <bean class="com.yx.AOP.advice.MyAfterReturningAdvice" id="myAfterReturningAdvice"></bean>
<!--    环绕通知-->
    <bean class="com.yx.AOP.advice.MyMethodInterceptor" id="methodInterceptor"></bean>
<!--    异常通知-->
    <bean class="com.yx.AOP.advice.MyThrowsAdvice" id="throwsAdvice"></bean>
<!--    过滤通知-->
    <bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="regexpMethodPointcutAdvisor">
        <property name="advice" ref="myAfterReturningAdvice"></property>
<!--        编写正则-->
        <property name="pattern" value=".*buy"></property>
    </bean>
<!--代理-->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="bookProxy">
<!--        配置目标对象-->
        <property name="target" ref="bookBiz"></property>
<!--        配置代理接口,目标对象的接口-->
        <property name="proxyInterfaces">
            <list>
                <value>com.yx.AOP.biz.IBookBiz</value>
            </list>
        </property>
        <!--        配置通知-->
        <property name="interceptorNames">
            <list>
<!--                前置通知-->
                <value>methodBeforeAdvice</value>
<!--                后置通知-->
<!--                <value>myAfterReturningAdvice</value>-->
<!--                环绕通知-->
                <value>methodInterceptor</value>
<!--                异常通知-->
                <value>throwsAdvice</value>
<!--                过滤通知-->
                <value>regexpMethodPointcutAdvisor</value>
            </list>
        </property>
    </bean>
</beans>

将后置通知的配置注释换成过滤通知。

测试Demo1代码
package com.yx.AOP.Demo;
import com.yx.AOP.biz.IBookBiz;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * @author 君易--鑨
 * @site www.yangxin.com
 * @company 木易
 * @create  2023-08-17 18:15
 * 测试类
 */
public class Demo1 {
   public static void main(String[] args) {
      ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("Spring-context.xml");
//      IBookBiz bookBiz = (IBookBiz) context.getBean("bookBiz");
      IBookBiz bookBiz = (IBookBiz) context.getBean("bookProxy");
      bookBiz.buy("木易","斗破苍穹",25d);
      bookBiz.comment("木易","太精彩了!!!");
   }
}
测试输出结果

四、总结

AOP是一个面向切面编程(Aspect-Oriented Programming,AOP)的编程范式,程序一般是由上到下执行,但是AOP面向切面不是。AOP的程序执行,首先当程序执行到目标对象的目标方法时,

五、扩展

1. 如何在项目中去使用AOP

1.1 实现步骤

  1. 引入AOP框架:选择适合你项目的AOP框架,比如Spring框架的AOP模块或AspectJ框架。根据项目的需求和技术栈选择相应的框架,并将其添加到项目的依赖中。
  2. 定义切面:在项目中创建切面类,这个类将包含横切关注点的逻辑。你可以使用注解或XML配置方式创建切面。
  3. 定义切点:在切面类中定义切点,选择你感兴趣的目标方法或类。切点使用切点表达式来匹配方法和类,你可以使用切点表达式指定匹配的条件,如方法名、类名、包名等。
  4. 编写通知:在切面类中编写通知代码,根据你的需求选择适当类型的通知,如@Before@After@Around等。通知是在切点上执行的代码片段,你可以在通知中添加需要的逻辑,如日志记录、事务管理、权限检查等。
  5. 将切面织入目标对象:通过配置文件或注解等方式将切面织入到目标对象中。这可以在Spring框架中使用<aop:aspectj-autoproxy>元素进行自动代理,或者使用@Aspect注解标记切面类。
  6. 测试和调试:在项目中验证AOP是否按预期工作。执行一些被切点匹配的方法,观察通知是否按照定义的切面逻辑执行。

1.2 使用时的注意事项

  • 了解AOP框架的具体用法和配置方式,参考相关文档和示例。
  • 将AOP的关注点分离出来,确保切面的逻辑单一和职责清晰
  • 根据项目需求选择合适的切点表达式,不要使用过于宽泛的表达式,以免匹配到不相关的方法或类。
  • 进行适当的测试和调试,验证切面的行为是否符合预期。
  • 关注切面的性能影响,确保AOP操作的效率和可扩展性

2. AOP与OOP的区别及各自的优势

2.1 区别:

  1. 关注点不同:OOP关注对象及其行为,将代码组织成对象的集合,通过封装、继承和多态等机制实现代码的模块化。而AOP关注横切关注点,这些关注点通常不是特定的类或对象所特有的,而是跨越多个对象或层次的通用功能。
  2. 抽象级别不同:OOP在语言级别上提供了类、继承、多态等概念和机制,以支持面向对象的设计和编程。而AOP是对OOP的一种补充,它在更高的抽象级别上考虑系统中的横切关注点,通过横切关注点的抽象描述和通用切面逻辑来增强系统的功能。
  3. 关注点分离:OOP通过封装将相关逻辑组织在对象中,实现了关注点的局部化。而AOP通过将横切关注点从业务逻辑中分离出来,实现了关注点的集中化和复用

2.2 各自的优势:

OOP的优势:
  • 模块化和可维护性:OOP通过封装、继承和多态等机制,实现了代码的模块化,使得代码易于理解、扩展和维护
  • 重用性:OOP提倡代码的重用,可以通过继承和组合等方式实现代码的复用减少代码冗余。
  • 可扩展性:OOP的继承和多态机制使得系统易于扩展和演化,可以通过添加新的子类或实现新的接口来引入新功能。
AOP的优势:
  • 关注点分离:AOP将横切关注点从业务逻辑中分离出来,减少了代码的重复性,增加了代码的可维护性和可重用性。
  • 横向扩展:AOP可以轻松地在不修改目标对象代码的情况下,添加、修改或删除横切逻辑,改变系统的行为,提高了系统的灵活性。
  • 增强系统功能:AOP可以通过在运行时动态地织入切面,增加新的功能和行为,如日志记录、安全检查、事务管理等。

感谢老铁们的阅读与支持,希望老铁能够三连一波,这无疑是对我最大的支持。请敬请期待下期博客的分享,我们下期再见。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
2月前
|
XML Java 开发者
Spring Boot中的AOP实现
Spring AOP(面向切面编程)允许开发者在不修改原有业务逻辑的情况下增强功能,基于代理模式拦截和增强方法调用。Spring Boot通过集成Spring AOP和AspectJ简化了AOP的使用,只需添加依赖并定义切面类。关键概念包括切面、通知和切点。切面类使用`@Aspect`和`@Component`注解标注,通知定义切面行为,切点定义应用位置。Spring Boot自动检测并创建代理对象,支持JDK动态代理和CGLIB代理。通过源码分析可深入了解其实现细节,优化应用功能。
116 6
|
1月前
|
XML Java 测试技术
Spring AOP—通知类型 和 切入点表达式 万字详解(通俗易懂)
Spring 第五节 AOP——切入点表达式 万字详解!
95 25
|
1月前
|
XML 安全 Java
Spring AOP—深入动态代理 万字详解(通俗易懂)
Spring 第四节 AOP——动态代理 万字详解!
79 24
|
2月前
|
存储 安全 Java
Spring Boot 3 集成Spring AOP实现系统日志记录
本文介绍了如何在Spring Boot 3中集成Spring AOP实现系统日志记录功能。通过定义`SysLog`注解和配置相应的AOP切面,可以在方法执行前后自动记录日志信息,包括操作的开始时间、结束时间、请求参数、返回结果、异常信息等,并将这些信息保存到数据库中。此外,还使用了`ThreadLocal`变量来存储每个线程独立的日志数据,确保线程安全。文中还展示了项目实战中的部分代码片段,以及基于Spring Boot 3 + Vue 3构建的快速开发框架的简介与内置功能列表。此框架结合了当前主流技术栈,提供了用户管理、权限控制、接口文档自动生成等多项实用特性。
93 8
|
4月前
|
XML Java 数据安全/隐私保护
Spring Aop该如何使用
本文介绍了AOP(面向切面编程)的基本概念和术语,并通过具体业务场景演示了如何在Spring框架中使用Spring AOP。文章详细解释了切面、连接点、通知、切点等关键术语,并提供了完整的示例代码,帮助读者轻松理解和应用Spring AOP。
112 2
Spring Aop该如何使用
|
4月前
|
监控 安全 Java
什么是AOP?如何与Spring Boot一起使用?
什么是AOP?如何与Spring Boot一起使用?
116 5
|
4月前
|
Java 开发者 Spring
深入解析:Spring AOP的底层实现机制
在现代软件开发中,Spring框架的AOP(面向切面编程)功能因其能够有效分离横切关注点(如日志记录、事务管理等)而备受青睐。本文将深入探讨Spring AOP的底层原理,揭示其如何通过动态代理技术实现方法的增强。
115 8
|
4月前
|
Java 开发者 Spring
Spring AOP 底层原理技术分享
Spring AOP(面向切面编程)是Spring框架中一个强大的功能,它允许开发者在不修改业务逻辑代码的情况下,增加额外的功能,如日志记录、事务管理等。本文将深入探讨Spring AOP的底层原理,包括其核心概念、实现方式以及如何与Spring框架协同工作。
|
4月前
|
安全 Java 编译器
什么是AOP面向切面编程?怎么简单理解?
本文介绍了面向切面编程(AOP)的基本概念和原理,解释了如何通过分离横切关注点(如日志、事务管理等)来增强代码的模块化和可维护性。AOP的核心概念包括切面、连接点、切入点、通知和织入。文章还提供了一个使用Spring AOP的简单示例,展示了如何定义和应用切面。
594 1
什么是AOP面向切面编程?怎么简单理解?
|
4月前
|
XML 监控 安全
深入调查研究Spring AOP
【11月更文挑战第15天】
66 5