• spring:详解面相切面编程AOP


    AOP

    AOP (Aspect Oriented Programming) 是另一个核心概念。它是一种程序设计的方法,允许程序员将横切关注点(如日志记录、性能监测等)区别于业务逻辑代码,并通过将它们独立地定义为切面来实现。在Spring框架中,AOP可以通过使用注解或XML配置来实现。

    Spring中的AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,用于处理那些在各个组件中经常出现的交叉关注点(cross-cutting concerns),比如日志记录、事务管理、安全性等。AOP使得这些关注点可以在合适的时机、以适当的方式被引入到程序中,而无需修改原有代码。

    代理机制

    AOP 背后的原理

    基于xml使用AOP

    暂时不学

    基于注解使用AOP

    相关注解

    1. @Aspect:表示一个切面类,通常用于定义切入点(pointcut)和通知(advice)。
    2. @Pointcut:表示一个切入点,用于指定哪些方法应该被切面所包含。可以使用表达式来定义切入点,如execution(* com.example…(…))表示com.example包下所有类的所有方法。
    3. @Before:表示前置通知,在目标方法执行前执行。
    4. @After:表示后置通知,在目标方法执行后执行。
    5. @AfterReturning:表示返回后通知,在目标方法正常返回后执行。
    6. @AfterThrowing:表示抛出异常后通知,在目标方法抛出异常后执行。
    7. @Around:表示环绕通知,可以自定义目标方法的执行前、执行后、返回前、返回后的逻辑。

    例一

    定义一个切面类:

    import org.aspectj.lang.annotation.*;  
      
    @Aspect  
    public class LoggingAspect {  
        @Before("execution(* com.example.*.*(..))")  
        public void logBefore(JoinPoint joinPoint) {  
            System.out.println("Before method: " + joinPoint.getSignature().getName());  
        }  
      
        @After("execution(* com.example.*.*(..))")  
        public void logAfter(JoinPoint joinPoint) {  
            System.out.println("After method: " + joinPoint.getSignature().getName());  
        }  
      
        @Around("execution(* com.example.*.*(..))")  
        public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {  
            long startTime = System.currentTimeMillis();  
            Object result = joinPoint.proceed();  
            long endTime = System.currentTimeMillis();  
            System.out.println("Method executed in " + (endTime - startTime) + " ms");  
            return result;  
        }  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在Spring配置文件中开启AOP支持:

    <aop:aspectj-autoproxy />
    
    • 1

    定义一个目标类:

    import org.springframework.stereotype.Component;  
      
    @Component  
    public class MyService {  
        public String doSomething() {  
            // some logic here...  
            return "result";  
        }  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这个例子中,LoggingAspect定义了一个切面类,它包含三个通知:logBefore、logAfter和logAround。@Before和@After注解表示在com.example包下所有类的所有方法执行前和执行后分别打印日志。@Around注解表示在com.example包下所有类的所有方法执行时打印方法的执行时间。最后,我们在Spring配置文件中开启了对AspectJ的支持,并定义了一个目标类MyService。当我们在应用中使用MyService时,就会自动应用LoggingAspect中定义的通知逻辑。

    例二

    例如,我们可以在一个方法执行前后分别记录日志和执行事务管理操作。如果我们使用面向切面编程,则可以将这些操作作为一个切面(Aspect)定义出来,并在方法执行前后自动执行这些操作。这样我们就可以避免在每个方法中都重复编写这些代码,从而提高代码的可维护性和可读性。

    @Aspect  
    public class LoggingAspect {  
      
        @Before("execution(public * com.example.demo.service.*.*(..))")  
        public void logBefore(JoinPoint joinPoint) {  
            System.out.println("Before method: " + joinPoint.getSignature().getName());  
        }  
      
        @After("execution(public * com.example.demo.service.*.*(..))")  
        public void logAfter(JoinPoint joinPoint) {  
            System.out.println("After method: " + joinPoint.getSignature().getName());  
        }  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在上述代码中,我们创建了一个名为LoggingAspect的切面类,并通过@Aspect注解进行标记。然后,我们定义了两个方法logBefore和logAfter,它们分别在目标方法执行前和执行后被调用。通过使用@Before和@After注解,我们可以指定这些方法在哪些目标方法执行前或执行后被调用。在本例中,我们使用了通配符来指定所有位于com.example.demo.service包下的类的所有公共方法。

    <beans xmlns="http://www.springframework.org/schema/beans"  
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
        xmlns:aop="http://www.springframework.org/schema/aop"  
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">  
      
          
      
        <bean id="loggingAspect" class="com.example.demo.aspects.LoggingAspect"/>  
      
        <aop:config>  
            <aop:aspect ref="loggingAspect">  
                <aop:before method="logBefore" pointcut="execution(public * com.example.demo.service.*.*(..))"/>  
                <aop:after method="logAfter" pointcut="execution(public * com.example.demo.service.*.*(..))"/>  
            aop:aspect>  
        aop:config>  
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在上述代码中,我们通过使用元素来创建LoggingAspect类的实例,并使用元素来启用AOP支持。然后,我们使用元素来指定切面类,并使用元素来定义切面方法的目标方法在执行前和执行后被调用。在本例中,我们使用了与切面类中相同的pointcut表达式来指定目标方法。

  • 相关阅读:
    STL标准模板库
    即时零售业态下如何实现自动做账?
    一些事宜记录
    万字长文 - Python 日志记录器logging 百科全书 - 高级配置之 日志分层
    怎么将PNG, JPEG, GIF,BMP等格式图片转化为ICO格式文件?
    【Spring】@RequestBody的实现原理
    30天Python入门(第十二天:深入了解Python中的模块)
    LeetCode讲解篇之40. 组合总和 II
    毕业设计项目选题Java高考志愿咨询平台 高考志愿填报助手系统源码+调试+开题+lw
    一步一步介绍如何将 OpenCV C++ 代码转换为 Python 模块
  • 原文地址:https://blog.csdn.net/weixin_43972437/article/details/133753585