Spring boot AOP通过XML配置文件声明

通过 XML 配置文件声明

在前两篇博文和示例中,我们已经展示了如何通过注解配置去声明切面,下面我们看看如何在 XML 文件中声明切面。下面先列出 XML 中声明 AOP 的常用元素:

AOP配置元素 用途
aop:advisor 定义AOP通知器
aop:after 定义AOP后置通知(不管被通知的方法是否执行成功)
aop:after-returning 定义AOP返回通知
aop:after-throwing 定义AOP异常通知
aop:around 定义AOP环绕通知
aop:aspect 定义一个切面
aop:aspectj-autoproxy 启用@AspectJ注解驱动的切面
aop:before 定义一个AOP前置通知
aop:config 顶层的AOP配置元素。大多数的aop:*元素必须包含在aop:config元素内
aop:declare-parents 以透明的方式为被通知的对象引入额外的接口
aop:pointcut 定义一个切点

XML 配置文件中切点指示器

在XML配置文件中,切点指示器表达式与通过注解配置的写法基本一致,区别前面有提到,即XML文件中需要使用 “and”、“or”、“not”来表示 “且”、“或”、“非”的关系。

XML 文件配置 AOP 

新建OrderXmlAop.java:

package com.example.demo.aop;

public class OrderXmlAop {

  /**
   * @description 在连接点执行之前执行的通知
   */
  public void doBefore(){
    System.out.println("阿里阿塞哟!");
  }

  /**
   * @description 在连接点执行之后执行的通知(返回通知和异常通知的异常)
   */
  public void doAfter(){
    System.out.println("after!");
  }

  /**
   * @description 在连接点执行之后执行的通知(返回通知)
   */
   public void doAfterReturning(){

     System.out.println("返回通知:AfterReturning");
   }

  /**
   * @description 在连接点执行之后执行的通知(异常通知)
   */
  public void doAfterThrowing(){
   System.out.println("异常通知:AfterThrowing");
   }
}

在 Resource 目录下新建一个配置文件 aoporder.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" xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

  <bean id="wmzService" class="com.example.demo.service.impl.WMZServiceImpl"></bean>
  <bean id="zsService" class="com.example.demo.service.impl.ZSServiceImpl"></bean>
  <!-- 切面类 -->
  <bean id="OrderXmlAop" class="com.example.demo.aop.OrderXmlAop"></bean>

  <!-- Aop配置 -->
  <aop:config proxy-target-class="true">

    <!-- 切面 -->
    <aop:aspect ref="OrderXmlAop">
      <!-- 前置通知: 在目标方法调用前执行 -->
      <aop:before pointcut="execution(public * com.example.demo.service.TakeawayService.*(..)))" method="doBefore"/>
      <!-- 后置通知: -->
      <aop:after pointcut="execution(public * com.example.demo.service.TakeawayService.*(..)))" method="doAfter"/>
      <!-- 返回后通知 -->
      <aop:after-returning pointcut="execution(public * com.example.demo.service.TakeawayService.*(..)))" method="doAfterReturning"/>
      <!-- 异常通知 -->
      <aop:after-throwing pointcut="execution(public * com.example.demo.service.TakeawayService.*(..)))" method="doAfterThrowing"/>
    </aop:aspect>
  </aop:config>
</beans>

新建 TakeXmlController.java

package com.example.demo.controller;

import com.example.demo.entity.Response;
import com.example.demo.entity.ResponseResult;
import jdk.internal.org.objectweb.asm.tree.analysis.Value;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.service.TakeawayService;
@RestController
@RequestMapping("/api")

public class TakeXmlController {

  ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("aoporder.xml");
  @RequestMapping("/orderxml")
  public ResponseResult Ordexml()
  {
    /**
    ** 注意 此处的getBean(name)中的name 必须要和aoporder.xml 配置的bean节点上的id 保持一致
     * 如: <bean id="wmzService" class="com.example.demo.service.impl.WMZServiceImpl"></bean>
     * TakeawayService wmzService=(TakeawayService)context.getBean("wmzService");
     */
    TakeawayService wmzService=(TakeawayService)context.getBean("wmzService");
    String wmz= wmzService.Order(12);
    System.out.println(wmz);
    TakeawayService zsService=(TakeawayService)context.getBean("zsService");
    String zs=zsService.Order(4396);
    System.out.println(zs);
    return Response.makeOKRsp(wmz+";"+zs);
  }
}

运行结果:

声明环绕通知

修改OrderXmlAop.java:

package com.example.demo.aop;

import org.aspectj.lang.ProceedingJoinPoint;

public class OrderXmlAop {

  /**
   * @description 在连接点执行之前执行的通知
   */
  public void doBefore(){
    System.out.println("阿里阿塞哟!");
  }

  /**
   * @description 在连接点执行之后执行的通知(返回通知和异常通知的异常)
   */
  public void doAfter(){
    System.out.println("after!");
  }

  /**
   * @description 在连接点执行之后执行的通知(返回通知)
   */
   public void doAfterReturning(){

     System.out.println("返回通知:AfterReturning");
   }

  /**
   * @description 在连接点执行之后执行的通知(异常通知)
   */
  public void doAfterThrowing(){
   System.out.println("异常通知:AfterThrowing");
   }

  /**
   * @description 在连接点执行之后执行的通知(异常通知)
   */
  public void doAround(ProceedingJoinPoint pj) {
    try {
      System.out.println("Around 调用方法前 ");
      pj.proceed();
      System.out.println("Around 调用方法后");
    } catch (Throwable throwable) {
      throwable.printStackTrace();
    }
  }
}

aoporder.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" xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

  <bean id="wmzService" class="com.example.demo.service.impl.WMZServiceImpl"></bean>
  <bean id="zsService" class="com.example.demo.service.impl.ZSServiceImpl"></bean>
  <!-- 切面类 -->
  <bean id="OrderXmlAop" class="com.example.demo.aop.OrderXmlAop"></bean>

  <!-- Aop配置 -->
  <aop:config proxy-target-class="true">

    <!-- 切面 -->
    <aop:aspect ref="OrderXmlAop">
      <!-- 环绕通知 -->
      <aop:around pointcut="execution(public * com.example.demo.service.TakeawayService.*(..)))" method="doAround"/>
      <!-- 前置通知: 在目标方法调用前执行 -->
      <aop:before pointcut="execution(public * com.example.demo.service.TakeawayService.*(..)))" method="doBefore"/>
      <!-- 后置通知: -->
      <aop:after pointcut="execution(public * com.example.demo.service.TakeawayService.*(..)))" method="doAfter"/>
      <!-- 返回后通知 -->
      <aop:after-returning pointcut="execution(public * com.example.demo.service.TakeawayService.*(..)))" method="doAfterReturning"/>
      <!-- 异常通知 -->
      <aop:after-throwing pointcut="execution(public * com.example.demo.service.TakeawayService.*(..)))" method="doAfterThrowing"/>
    </aop:aspect>
  </aop:config>
</beans>

运行结果:

结果和我们预期的一致,环绕通知通过xml配置成功。

XML 文件配置声明切点 

在上面的例子中,我们发现有切点表达式多次重复出现,那么可不可以和aspectj配置一样,单独声明切点,后面复用,答案是当然可以。如下修改aoporder.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" xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

  <bean id="wmzService" class="com.example.demo.service.impl.WMZServiceImpl"></bean>
  <bean id="zsService" class="com.example.demo.service.impl.ZSServiceImpl"></bean>
  <!-- 切面类 -->
  <bean id="OrderXmlAop" class="com.example.demo.aop.OrderXmlAop"></bean>

  <!-- Aop配置 -->
  <aop:config proxy-target-class="true">
    <!-- 切点 -->
    <aop:pointcut id="point" expression="execution(public * com.example.demo.service.TakeawayService.*(..)))"/>
    <!-- 切面 -->
    <aop:aspect ref="OrderXmlAop">
      <!-- 环绕通知 -->
      <aop:around pointcut-ref="point" method="doAround"/>
      <!-- 前置通知: 在目标方法调用前执行 -->
      <aop:before pointcut-ref="point" method="doBefore"/>
      <!-- 后置通知: -->
      <aop:after pointcut-ref="point" method="doAfter"/>
      <!-- 返回后通知 -->
      <aop:after-returning pointcut-ref="point" method="doAfterReturning"/>
      <!-- 异常通知 -->
      <aop:after-throwing pointcut-ref="point" method="doAfterThrowing"/>
    </aop:aspect>
  </aop:config>
</beans>

修改后执行结果:

XML文件配置为通知传递参数

修改OrderXmlAop.java

public String doAround(ProceedingJoinPoint pj,double price) {
    try {
      System.out.println("Around 调用方法前 ");
      pj.proceed();
      if(price>=4396)
      {
        System.out.println("zs下单超过了4399,赠送一份鲜果饮汇源牌饮料");
        return "爆浆牛丸和饮料";
      }
      System.out.println("Around 调用方法后");
    } catch (Throwable throwable) {
      throwable.printStackTrace();
    }
    return "爆浆牛丸";
  }

修改aoporder.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" xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

  <bean id="wmzService" class="com.example.demo.service.impl.WMZServiceImpl"></bean>
  <bean id="zsService" class="com.example.demo.service.impl.ZSServiceImpl"></bean>
  <!-- 切面类 -->
  <bean id="OrderXmlAop" class="com.example.demo.aop.OrderXmlAop"></bean>

  <!-- Aop配置 -->
  <aop:config proxy-target-class="true">
    <!-- 切点 -->
    <aop:pointcut id="point" expression="execution(com.example.demo.service.TakeawayService.Order(double)) and args(price) and bean(zsService)"/>
    <!-- 切面 -->
    <aop:aspect ref="OrderXmlAop">
      <!-- 环绕通知 -->
      <aop:around pointcut-ref="point" method="doAround"/>
    </aop:aspect>
  </aop:config>
</beans>

总结

本文主要通过XML配置文件使用 Spring AOP进行编程,和上一篇的注解方式两者联系起来对于刚入门的应该多多少少还是有点帮助的吧,针对于aop 通过三篇博客简单的描述,相信大家对此都有点印象了,记录了 AOP 的编程思想,然后介绍了 Spring 中 AOP 的相关概念,以及通过注解方式和XML配置文件两种方式使用 Spring AOP进行编程。所以对aop的博文就简单到这儿了,有人要问了,aop里面的代理啊还有各种各样的,如果真要吧aop重头到尾来一遍的话,这个系列可以单独提出来一个专栏了,所以后面的博文应该都是围绕连接数据库,记录日志,接入swagger文档等功能相继展开了。在此过程中,我有错误使用的地方,或者表达有问题,还请您及时告知,本人会在第一时间予以改正。最后在祝大家周末愉快,C Y L L

(0)

相关推荐

  • SpringBoot通过yml和xml文件配置日志输出方法

    SpringBoot中默认使用Logback进行日志输出,可以同时使用SpringBoot框架的配置文件application.yml或是通过logback的配置文件logback.xml进行配置. 通过application.yml配置 <?xml version="1.0" encoding="UTF-8"?> <configuration debug="false"> <!--定义日志文件的存储地址 勿在 Lo

  • 详解springboot集成mybatis xml方式

    springboot集成mybatis 关键代码如下: 1,添加pom引用 <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.1.1</version> </dependency> <dependency> &l

  • SpringBoot返回json和xml的示例代码

    有些情况接口需要返回的是xml数据,在springboot中并不需要每次都转换一下数据格式,只需做一些微调整即可. 新建一个springboot项目,加入依赖jackson-dataformat-xml,pom文件代码如下: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=&qu

  • 详解SpringBoot 快速整合MyBatis(去XML化)

    序言: 此前,我们主要通过XML来书写SQL和填补对象映射关系.在SpringBoot中我们可以通过注解来快速编写SQL并实现数据访问.(仅需配置:mybatis.configuration.map-underscore-to-camel-case=true).为了方便大家,本案例提供较完整的层次逻辑SpringBoot+MyBatis+Annotation. 具体步骤 1. 引入依赖 在pom.xml 引入ORM框架(Mybaits-Starter)和数据库驱动(MySQL-Conn)的依赖.

  • SpringBoot项目设置断点debug调试无效忽略web.xml问题的解决

    刚接触springboot项目, (1)发现断点debug调试无效,很郁闷,网上搜索解决办法. 看到的都是一些很复杂的方案,说是远程调试,还要另外开端口号.这和传统的项目不一样,因此觉得没必要. 所以经过摸索,发现有一种更加简单的方式,步骤如下: 在pom文件的plugin部分加上一段配置: <configuration> <fork>false</fork> </configuration> 这样就ok了: (2)关于SpringBoot项目中报错说web

  • SpringBoot之logback-spring.xml不生效的解决方法

    一.前言 做新应用就是这样,会遇到各种问题,昨天刚解决了加载某一个类时候抛出了 class is not visible from class loader 的问题,今天就有遇到了日志文件找不到的问题,还是和二方库有关的,下面就一一道来. 二.问题产生 正常情况下在  src/main/resources 目录放下  logback-spring.xml 的配置文件(使用logback日志系统),如下图 application.properties里面设置  spring.application

  • 详解SpringBoot 快速整合Mybatis(去XML化+注解进阶)

    序言:使用MyBatis3提供的注解可以逐步取代XML,例如使用@Select注解直接编写SQL完成数据查询,使用@SelectProvider高级注解还可以编写动态SQL,以应对复杂的业务需求. 一. 基础注解 MyBatis 主要提供了以下CRUD注解: @Select @Insert @Update @Delete 增删改查占据了绝大部分的业务操作,掌握这些基础注解的使用是很必要的.例如下面这段代码无需XML即可完成数据查询: @Mapper public interface UserMa

  • springboot使用Mybatis(xml和注解)过程全解析

    刚毕业的第一份工作是 java 开发,项目中需要用到 mybatis,特此记录学习过程,这只是一个简单 demo,mybatis 用法很多不可能全部写出来,有更复杂的需求建议查看 mybatis 的官方中文文档,点击跳转.下面时项目环境/版本. •开发工具:IDEA •jdk 版本:1.8 •springboot 版本:2.03 其他依赖版本见下面 pom.xml: <?xml version="1.0" encoding="UTF-8"?> <p

  • Spring Boot中扩展XML请求与响应的支持详解

    前言 在之前的所有Spring Boot教程中,我们都只提到和用到了针对HTML和JSON格式的请求与响应处理.那么对于XML格式的请求要如何快速的在Controller中包装成对象,以及如何以XML的格式返回一个对象呢? 什么是xml文件格式 我们要给对方传输一段数据,数据内容是"too young,too simple,sometimes naive",要将这段话按照属性拆分为三个数据的话,就是,年龄too young,阅历too simple,结果sometimes naive.

  • SpringBoot 整合 dubbo xml实现代码示例

    昨天发布了注解方式,有人给我发了邮件希望能出一版本xml格式的,本来12点前能搞定的但是电脑稍微出了问题,导致idea 疯狂奔溃,搞了很久废话不多说了,有错误之处望大家指出发我邮箱. 用dubbo肯定是多模块化了 所以我们先创建一个聚合项目 这是项目结构 Dubbo_demo 的pom 这个主要用来聚合业务模块用不做任何业务处理 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="

随机推荐