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月前
|
Java
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
这篇文章是Spring5框架的实战教程,深入讲解了AOP的基本概念、如何利用动态代理实现AOP,特别是通过JDK动态代理机制在不修改源代码的情况下为业务逻辑添加新功能,降低代码耦合度,并通过具体代码示例演示了JDK动态代理的实现过程。
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
|
15天前
|
设计模式 Java 测试技术
spring复习04,静态代理动态代理,AOP
这篇文章讲解了Java代理模式的相关知识,包括静态代理和动态代理(JDK动态代理和CGLIB),以及AOP(面向切面编程)的概念和在Spring框架中的应用。文章还提供了详细的示例代码,演示了如何使用Spring AOP进行方法增强和代理对象的创建。
spring复习04,静态代理动态代理,AOP
|
3月前
|
Java Spring
在Spring Boot中使用AOP实现日志切面
在Spring Boot中使用AOP实现日志切面
|
29天前
|
Java 数据库连接 数据库
Spring基础3——AOP,事务管理
AOP简介、入门案例、工作流程、切入点表达式、环绕通知、通知获取参数或返回值或异常、事务管理
Spring基础3——AOP,事务管理
|
2月前
|
XML Java 数据格式
Spring5入门到实战------11、使用XML方式实现AOP切面编程。具体代码+讲解
这篇文章是Spring5框架的AOP切面编程教程,通过XML配置方式,详细讲解了如何创建被增强类和增强类,如何在Spring配置文件中定义切入点和切面,以及如何将增强逻辑应用到具体方法上。文章通过具体的代码示例和测试结果,展示了使用XML配置实现AOP的过程,并强调了虽然注解开发更为便捷,但掌握XML配置也是非常重要的。
Spring5入门到实战------11、使用XML方式实现AOP切面编程。具体代码+讲解
|
2月前
|
缓存 Java 开发者
Spring高手之路22——AOP切面类的封装与解析
本篇文章深入解析了Spring AOP的工作机制,包括Advisor和TargetSource的构建与作用。通过详尽的源码分析和实际案例,帮助开发者全面理解AOP的核心技术,提升在实际项目中的应用能力。
29 0
Spring高手之路22——AOP切面类的封装与解析
|
2月前
|
安全 Java 开发者
Java 新手入门:Spring 两大利器IoC 和 AOP,小白也能轻松理解!
Java 新手入门:Spring 两大利器IoC 和 AOP,小白也能轻松理解!
31 1
|
2月前
|
Java Spring
Spring的AOP组件详解
该文章主要介绍了Spring AOP(面向切面编程)组件的实现原理,包括Spring AOP的基础概念、动态代理模式、AOP组件的实现以及Spring选择JDK动态代理或CGLIB动态代理的依据。
Spring的AOP组件详解
|
2月前
|
Java API Spring
Spring Boot 中的 AOP 处理
对 Spring Boot 中的切面 AOP 做了详细的讲解,主要介绍了 Spring Boot 中 AOP 的引入,常用注解的使用,参数的使用,以及常用 api 的介绍。AOP 在实际项目中很有用,对切面方法执行前后都可以根据具体的业务,做相应的预处理或者增强处理,同时也可以用作异常捕获处理,可以根据具体业务场景,合理去使用 AOP。
|
2月前
|
Java Spring XML
掌握面向切面编程的秘密武器:Spring AOP 让你的代码优雅转身,横切关注点再也不是难题!
【8月更文挑战第31天】面向切面编程(AOP)通过切面封装横切关注点,如日志记录、事务管理等,使业务逻辑更清晰。Spring AOP提供强大工具,无需在业务代码中硬编码这些功能。本文将深入探讨Spring AOP的概念、工作原理及实际应用,展示如何通过基于注解的配置创建切面,优化代码结构并提高可维护性。通过示例说明如何定义切面类、通知方法及其应用时机,实现方法调用前后的日志记录,展示AOP在分离关注点和添加新功能方面的优势。
44 0