zoukankan      html  css  js  c++  java
  • [08] AOP基本概念和使用


    1、什么是AOP

    AOP = Aspect Oriental Programing,即面向切面编程。什么概念,我们看如下的图片:

    三个方法中,重复使用了代码A和代码B,典型的场景比如“开启事务,数据处理,提交事务”。这些重复的代码大多是所谓的权限管理、日志登陆、事务管理等必需却又污染着业务逻辑代码的内容,我们自然希望将它们提取出来,还业务逻辑一个清新的世界。

    你知道Servlet过滤器,可我们目前对象的粒度已经不是整个方法了,而是更加细化到了方法中的代码片段。你当然可以曲线救国地使用匿名内部类来抽取重复代码,但是它并不怎么优雅,而AOP,就可以通过横向切割的方式来抽取代码,达到我们的目的。

    2、Spring AOP

    首先来看一下Spring AOP中一些核心组件的概念:
    • 切面:封装通用业务逻辑的组件,即我们想要插入的代码内容
    • 切入点:指定哪些Bean组件的哪些方法使用切面组件
    • 通知:用于指定具体作用的位置,是方法之前或之后等等
      • 前置通知(before) - 在目标方法被调用之前调用通知功能
      • 后置通知(after) - 在目标方法完成之后调用通知(不论程序是否出现异常),此时不会关心方法的输出是什么
      • 返回通知(after-returning) - 在目标方法成功执行之后调用通知
      • 异常通知(after-throwing) - 在目标方法抛出异常后调用通知
      • 环绕通知(around) - 通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为

    那么在Spring中使用AOP就意味着你需要:
    • 目标程序,某个需要被插入通用代码片段的方法
    • 切面程序,即通用代码,用来插入方法的那些代码片段(无返回类型,参数类型与通知类型有关)
    • 配置文件,用来指定切入点和通知

    3、Demo示例和说明

    下面就来看一个简单的Spring AOP的Demo

    3.1相关配置环境

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.16.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>4.3.16.RELEASE</version>
    </dependency>

    3.2 准备一个目标程序

    编写某个目标程序,并注册为Spring的Bean组件
    public class Target {
    
        public void print(String param) {
            System.out.println("I'm a target function and my param is [" + param + "]" );
        }
    
    }

    3.3 编写切面程序

    编写切面程序,并注册为Spring的Bean组件
    • 切面程序必须无返回值,即void
    • org.aspectj.lang.JoinPoint 封装了切面方法的参数和对象等,可通过它获取相关内容
    • 切面程序的参数除JoinPoint外,还与通知类型有关,如后置通知则可以获取目标程序返回值(需要配置,此处不展开)
    public class Section {
    
        public void writeLog(JoinPoint point) {
            System.out.println("write logs start");
    
            System.out.println("获取目标函数的参数: " + Arrays.toString(point.getArgs()));
            System.out.println("获取目标函数的反射对象: " + point.getSignature());
            System.out.println("获取目标函数的所在对象: " + point.getTarget());
    
            System.out.println("write logs end");
        }
    
    }

    3.4 编写AOP配置文件

    配置文件applicationContext(注册Bean和AOP配置)
    <bean id="target" class="dulk.learn.aop.Target"/>
    <bean id="section" class="dulk.learn.aop.Section"/>
    
    <!-- AOP配置的根标签,所有AOP配置都在其内部 -->
    <aop:config>
        <!-- 配置AOP的切入点,expression为切入点表达式 -->
        <aop:pointcut id="targetPointCut" expression="execution(* dulk.learn.aop.Target.print(*))" />
        <!-- 配置切面,ref 切面对象 -->
        <aop:aspect ref="section">
            <!-- 配置通知为前置,method为方法,pointcut-ref作用在哪些切入点 -->
            <aop:before method="writeLog" pointcut-ref="targetPointCut"/>
        </aop:aspect>
    
    </aop:config>

    3.4.1 切入表达式


    如上说明,则该demo中的 execution(* dulk.learn.aop.Target.print(*)) 表示 “Target类中的print方法(不论参数,即包括其重载)”

    3.4.2 切面配置说明

    <!-- 配置切面,ref 切面对象的beanId -->
    <aop:aspect ref="section">
        <!-- before表通知为前置,method为插入的方法,pointcut-ref作用在哪些切入点(aop:pointcut id) -->
        <aop:before method="writeLog" pointcut-ref="targetPointCut"/>
    </aop:aspect>

    3.5 测试程序和结果

    public class AOPTest {
    
        @Test
        public void testAOP(){
            ApplicationContext context = new ClassPathXmlApplicationContext("/applicationContext.xml");
            Target target = (Target) context.getBean("target");
            target.print("balabala");
        }
    
    } 

     

    4、参考链接

  • 相关阅读:
    Docker容器启动时初始化Mysql数据库
    使用Buildpacks高效构建Docker镜像
    Mybatis 强大的结果集映射器resultMap
    Java 集合排序策略接口 Comparator
    Spring MVC 函数式编程进阶
    换一种方式编写 Spring MVC 接口
    【asp.net core 系列】6 实战之 一个项目的完整结构
    【asp.net core 系列】5 布局页和静态资源
    【asp.net core 系列】4. 更高更强的路由
    【Java Spring Cloud 实战之路】- 使用Nacos和网关中心的创建
  • 原文地址:https://www.cnblogs.com/deng-cc/p/9214557.html
Copyright © 2011-2022 走看看