Spring中Aop及日志通知

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Spring中Aop及日志通知

一.Aop简介

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


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


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


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

二.AOP与OOP

AOP(Aspect Oriented Programming)面向切面编程是 Spring 框架最核心的组件之一,它通过对程序结构的另一种考虑,补充了 OOP(Object-Oriented Programming)面向对象编程。在 OOP 中模块化的关键单元是类,而在 AOP 中,模块化单元是切面。也就是说 AOP 关注的不再是类,而是一系列类里面需要共同能力的行为。

三.AOP中的概念和机制

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

四.日志通知

3.1. 前置通知

spring-context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       default-autowire="byType"
       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.aop.biz.impl.BookBizImpl" name="bookBiz"></bean>
<!--通知-->
    <bean class="com.aop.biz.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.aop.biz.IBookBiz</value>
            </list>
        </property>
<!--配置通知-->
        <property name="interceptorNames">
            <list>
                <value>methodBeforeAdvice</value>
            </list>
        </property>
    </bean>
</beans>
package com.aop.biz.advice;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
 * 买书、评论前加系统日志
 * @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+")被调用了");
  }
}

3.2.后置通知

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

3.3. 环绕通知

package com.aop.advice;
import java.util.Arrays;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/**
 * 环绕通知
 *  包含了前置和后置通知
 * 
 * @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;
  }
}

3.4.异常通知

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

3.5.过滤通知

所有用到的bean:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       default-autowire="byType"
       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.aop.biz.impl.BookBizImpl" name="bookBiz"></bean>
<!--通知-->
    <bean class="com.aop.biz.advice.MyMethodBeforeAdvice" id="methodBeforeAdvice"></bean>
    <bean class="com.aop.biz.advice.MyAfterReturningAdvice" id="myAfterReturningAdvice"></bean>
    <bean class="com.aop.biz.advice.MyMethodInterceptor" id="myMethodInterceptor"></bean>
    <bean class="com.aop.biz.advice.MyThrowsAdvice" id="myThrowsAdvice"></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.aop.biz.IBookBiz</value>
            </list>
        </property>
<!--配置通知-->
        <property name="interceptorNames">
            <list>
                <value>methodBeforeAdvice</value>
<!--                <value>myAfterReturningAdvice</value>-->
                <value>regexpMethodPointcutAdvisor</value>
                <value>myMethodInterceptor</value>
                <value>myThrowsAdvice</value>
            </list>
        </property>
    </bean>
</beans>


五.AOP的使用场景

  • Authentication 权限
  • Caching 缓存
  • Context passing 内容传递
  • Error handling 错误处理
  • Lazy loading 懒加载
  • Debugging  调试
  • logging, tracing, profiling and monitoring 记录跟踪 优化 校准
  • Performance optimization 性能优化
  • Persistence  持久化
  • Resource pooling 资源池
  • Synchronization 同步
  • Transactions 事务

 好啦,今天的分享就到这了,希望能够帮到你呢!😊😊

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
6天前
|
设计模式 Java 测试技术
spring复习04,静态代理动态代理,AOP
这篇文章讲解了Java代理模式的相关知识,包括静态代理和动态代理(JDK动态代理和CGLIB),以及AOP(面向切面编程)的概念和在Spring框架中的应用。文章还提供了详细的示例代码,演示了如何使用Spring AOP进行方法增强和代理对象的创建。
spring复习04,静态代理动态代理,AOP
|
20天前
|
Java 数据库连接 数据库
Spring基础3——AOP,事务管理
AOP简介、入门案例、工作流程、切入点表达式、环绕通知、通知获取参数或返回值或异常、事务管理
Spring基础3——AOP,事务管理
|
2月前
|
缓存 Java 开发者
Spring高手之路22——AOP切面类的封装与解析
本篇文章深入解析了Spring AOP的工作机制,包括Advisor和TargetSource的构建与作用。通过详尽的源码分析和实际案例,帮助开发者全面理解AOP的核心技术,提升在实际项目中的应用能力。
23 0
Spring高手之路22——AOP切面类的封装与解析
|
2月前
|
Java Spring XML
掌握面向切面编程的秘密武器:Spring AOP 让你的代码优雅转身,横切关注点再也不是难题!
【8月更文挑战第31天】面向切面编程(AOP)通过切面封装横切关注点,如日志记录、事务管理等,使业务逻辑更清晰。Spring AOP提供强大工具,无需在业务代码中硬编码这些功能。本文将深入探讨Spring AOP的概念、工作原理及实际应用,展示如何通过基于注解的配置创建切面,优化代码结构并提高可维护性。通过示例说明如何定义切面类、通知方法及其应用时机,实现方法调用前后的日志记录,展示AOP在分离关注点和添加新功能方面的优势。
38 0
|
2月前
|
人工智能 Java Spring
Spring框架下,如何让你的日志管理像‘AI’一样智能,提升开发效率的秘密武器!
【8月更文挑战第31天】日志管理在软件开发中至关重要,不仅能帮助开发者追踪问题和调试程序,还是系统监控和运维的重要工具。在Spring框架下,通过合理配置Logback等日志框架,可大幅提升日志管理效率。本文将介绍如何引入日志框架、配置日志级别、在代码中使用Logger,以及利用ELK等工具进行日志聚合和分析,帮助你构建高效、可靠的日志管理系统,为开发和运维提供支持。
36 0
|
2月前
|
监控 Java Serverless
美团 Flink 大作业部署问题之想在Serverless平台上实时查看Spring Boot应用的日志要怎么操作
美团 Flink 大作业部署问题之想在Serverless平台上实时查看Spring Boot应用的日志要怎么操作
|
2月前
|
存储 Java Spring
【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
|
2月前
|
Java Linux C++
【Azure 应用服务】App Service For Linux 部署Java Spring Boot应用后,查看日志文件时的疑惑
【Azure 应用服务】App Service For Linux 部署Java Spring Boot应用后,查看日志文件时的疑惑
|
5月前
|
安全 Java Spring
Spring之Aop的底层原理
Spring之Aop的底层原理
|
5月前
|
设计模式 Java uml
Spring AOP 原理
Spring AOP 原理
31 0
下一篇
无影云桌面