12、Spring之基于xml的AOP

这篇具有很好参考价值的文章主要介绍了12、Spring之基于xml的AOP。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

阅读本文前,建议先阅读Spring之基于注解的AOP

12.1、环境搭建

创建名为spring_aop_xml的新module,过程参考9.1节

12.1.1、配置打包方式和依赖

12、Spring之基于xml的AOP

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.rain</groupId>
    <artifactId>spring_aop_xml</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
        <!-- Spring-IOC的依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.1</version>
        </dependency>

        <!-- spring-AOP的依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.3.1</version>
        </dependency>

        <!-- junit测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

12.1.2、创建Calculator接口及实现类

12、Spring之基于xml的AOP

package org.rain.spring.aop.xml;

/**
 * @author liaojy
 * @date 2023/8/18 - 8:09
 */
public interface Calculator {

    int add(int i, int j);
    int sub(int i, int j);
    int mul(int i, int j);
    int div(int i, int j);

}

12、Spring之基于xml的AOP

package org.rain.spring.aop.xml;

import org.springframework.stereotype.Component;

/**
 * @author liaojy
 * @date 2023/8/18 - 8:11
 */
// @Component注解:保证这个目标类能够放入IOC容器
@Component
public class CalculatorImpl implements Calculator {
    public int add(int i, int j) {

        int result = i + j;
        System.out.println("方法内部 result = " + result);
        return result;

    }

    public int sub(int i, int j) {

        int result = i - j;
        System.out.println("方法内部 result = " + result);
        return result;

    }

    public int mul(int i, int j) {

        int result = i * j;
        System.out.println("方法内部 result = " + result);
        return result;

    }

    public int div(int i, int j) {

        int result = i / j;
        System.out.println("方法内部 result = " + result);
        return result;

    }
}

12.1.3、创建切面类LoggerAspect

12、Spring之基于xml的AOP

package org.rain.spring.aop.xml;

import org.springframework.stereotype.Component;

/**
 * @author liaojy
 * @date 2023/8/18 - 8:15
 */
// @Component注解:保证这个目标类能够放入IOC容器
@Component
public class LoggerAspect {
}

12.1.4、创建spring配置文件

12、Spring之基于xml的AOP

<?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:context="http://www.springframework.org/schema/context"
       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/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--
        对指定的package进行扫描,将使用组件注解的类的对象(本示例是目标对象和切面对象),交给spring的ioc容器来管理
    -->
    <context:component-scan base-package="org.rain.spring.aop.xml"></context:component-scan>

</beans>

12.2、前置通知的使用

12.2.1、基本示例

12.2.1.1、定义前置通知的功能

12、Spring之基于xml的AOP

    public void beforeMethod(){
        System.out.println("LoggerAspect,前置通知");
    }

12.2.1.2、配置前置通知到切面

12、Spring之基于xml的AOP

    <aop:config>
        <!--
            aop:aspect标签:将ioc容器中的bean对象设置为切面,效果等同于@Aspect注解
                ref属性:引用IOC容器中(要设置为切面的)bean的id
        -->
        <aop:aspect ref="loggerAspect">
            <!--
                aop:before标签:将方法设置为该切面的前置通知(方法),效果等同于@Before注解
                    method属性:指定(要设置为前置通知的)方法的名称
                    pointcut属性:设置该前置通知的切入点表达式
            -->
            <aop:before method="beforeMethod" pointcut="execution(* org.rain.spring.aop.xml.CalculatorImpl.*(..))"></aop:before>
        </aop:aspect>
    </aop:config>

12.2.1.3、测试使用效果

12、Spring之基于xml的AOP

由控制台日志可知,切面类的前置通知(方法),通过切入点表达式,作用到了目标方法的连接点上

package org.rain.spring.aop.test;

import org.junit.Test;
import org.rain.spring.aop.xml.Calculator;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author liaojy
 * @date 2023/8/18 - 19:07
 */
public class AOPTest {

    @Test
    public void testAOPByXML(){
        ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-aopByxml.xml");
        // 注意:这里不能直接获取目标对象来使用;因为使用了AOP之后,IOC容器中就只有对应目标对象的代理对象;
        // 如果强行获取目标对象,则报错:NoSuchBeanDefinitionException
        //Calculator calculator = ioc.getBean(CalculatorImpl.class);

        // 虽然不知道代理对象的类名,但可以通过代理对象和目标对象共同实现的接口类型来从ioc容器中获取代理对象
        Calculator calculator = ioc.getBean(Calculator.class);

        // 只能通过代理对象来访问目标对象中的方法
        calculator.div(1,1);

    }
}

12.2.2、高级示例

12.2.2.1、改进前置通知的功能

12、Spring之基于xml的AOP

该示例中(前置)通知方法引入了连接点参数,通过连接点参数,可以动态获取(切入点表达式)对应的目标方法的名称和参数列表

    // joinPoint参数:可以获取(通过切入点表达式定位出的)连接点的相关信息
    public void beforeMethod(JoinPoint joinPoint){
        // 获取连接点所对应目标方法的名称
        String methodName = joinPoint.getSignature().getName();
        // 获取连接点所对应目标方法的参数列表
        Object[] args = joinPoint.getArgs();
        System.out.println("LoggerAspect-->前置通知,方法名:"+methodName+",参数:"+ Arrays.toString(args));
    }

12.2.2.2、测试使用效果

12、Spring之基于xml的AOP

12.3、切入点表达式的复用

切入点表达的详细语法,请参考11.3.2节

12.3.1、配置公共的切入点表达式

12、Spring之基于xml的AOP

        <!--
            aop:pointcut标签:用于声明公共的切入点表达式,效果等同于@Pointcut注解
                id属性:设置该公共切入点表达式的唯一标识
                expression属性:设置切入点表达式
        -->
        <aop:pointcut id="pointcutOne" expression="execution(* org.rain.spring.aop.xml.CalculatorImpl.*(..))"/>

12.3.2、使用公共的切入点表达式

12、Spring之基于xml的AOP

<!--
    aop:before标签:将方法设置为该切面的前置通知(方法),效果等同于@Before注解
        method属性:指定(要设置为前置通知的)方法的名称
        pointcut属性:设置该前置通知的切入点表达式
        pointcut-ref属性:通过id引用对应的公共切入点表达式
-->
<!--<aop:before method="beforeMethod" pointcut="execution(* org.rain.spring.aop.xml.CalculatorImpl.*(..))"></aop:before>-->
<aop:before method="beforeMethod" pointcut-ref="pointcutOne"></aop:before>

12.4、其他通知的使用

12.4.1、后置通知

12.4.1.1、定义后置通知的功能

12、Spring之基于xml的AOP

    public void afterMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("LoggerAspect-->后置通知,方法名:"+methodName+",参数:"+ Arrays.toString(args));
    }

12.4.1.2、配置后置通知到切面

12、Spring之基于xml的AOP

            <!--
                aop:after标签:将方法设置为该切面的后置通知(方法),效果等同于@After注解
            -->
            <aop:after method="afterMethod" pointcut-ref="pointcutOne"></aop:after>

12.4.1.3、测试使用效果

12、Spring之基于xml的AOP

由控制台日志可知,后置通知在目标对象方法的finally子句中执行(一般用于释放资源)

    @Test
    public void testAOPByXML(){
        ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-aopByxml.xml");

        // 虽然不知道代理对象的类名,但可以通过代理对象和目标对象共同实现的接口类型来从ioc容器中获取代理对象
        Calculator calculator = ioc.getBean(Calculator.class);

        // 只能通过代理对象来访问目标对象中的方法
        calculator.div(1,0);

    }

12.4.2、返回通知

12.4.2.1、定义返回通知的功能

12、Spring之基于xml的AOP

    public void afterReturningMethod(JoinPoint joinPoint,Object result){
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("LoggerAspect-->返回通知,方法名:"+methodName+",结果:"+ result);
    }

12.4.2.2、配置返回通知到切面

12、Spring之基于xml的AOP

<!--
    aop:after-returning标签:将方法设置为该切面的返回通知(方法),效果等同于@AfterReturning注解
        returning属性:指定返回通知(方法)中的某个参数(名),用于接收目标对象方法的返回值
-->
<aop:after-returning method="afterReturningMethod" pointcut-ref="pointcutOne" returning="result"></aop:after-returning>

12.4.2.3、测试使用效果

12、Spring之基于xml的AOP

返回通知在目标对象方法的返回值之后执行

    @Test
    public void testAOPByXML(){
        ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-aopByxml.xml");

        // 虽然不知道代理对象的类名,但可以通过代理对象和目标对象共同实现的接口类型来从ioc容器中获取代理对象
        Calculator calculator = ioc.getBean(Calculator.class);

        // 只能通过代理对象来访问目标对象中的方法
        calculator.div(1,1);

    }

12.4.3、异常通知

12.4.3.1、定义异常通知的功能

12、Spring之基于xml的AOP

    public void afterThrowingMethod(JoinPoint joinPoint,Exception ex){
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("LoggerAspect-->异常通知,方法名:"+methodName+",异常:"+ ex);
    }

12.4.3.2、配置异常通知到切面

12、Spring之基于xml的AOP

<!--
    aop:after-throwing标签:将方法设置为该切面的异常通知(方法),效果等同于@AfterThrowing注解
        throwing属性:指定异常通知(方法)中的某个参数(名),用于接收目标对象方法出现的异常
-->
<aop:after-throwing method="afterThrowingMethod" pointcut-ref="pointcutOne" throwing="ex" ></aop:after-throwing>

12.4.3.3、测试使用效果

12、Spring之基于xml的AOP

由控制台日志可知,异常通知在目标对象方法的catch子句中执行

    @Test
    public void testAOPByXML(){
        ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-aopByxml.xml");

        // 虽然不知道代理对象的类名,但可以通过代理对象和目标对象共同实现的接口类型来从ioc容器中获取代理对象
        Calculator calculator = ioc.getBean(Calculator.class);

        // 只能通过代理对象来访问目标对象中的方法
        calculator.div(1,0);

    }

12.5、环绕通知

12.5.1、定义环绕通知的功能

12、Spring之基于xml的AOP

环绕通知和动态代理的形式,非常相似

    /**
     *  环绕通知(方法)使用的参数是ProceedingJoinPoint类型
     *  环绕通知(方法)的返回值,必须和目标对象方法的返回值一致
     */
    public Object aroundMethod(ProceedingJoinPoint proceedingJoinPoint){
        String methodName = proceedingJoinPoint.getSignature().getName();
        Object[] args = proceedingJoinPoint.getArgs();
        Object result = null;
        try {
            System.out.println("LoggerAspect-->环绕前置通知,方法名:"+methodName+",参数:"+ Arrays.toString(args));
            // 表示目标对象方法的执行
            result = proceedingJoinPoint.proceed();
            System.out.println("LoggerAspect-->环绕返回通知,方法名:"+methodName+",结果:"+ result);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            System.out.println("LoggerAspect-->环绕异常通知,方法名:"+methodName+",异常:"+ throwable);
        }finally {
            System.out.println("LoggerAspect-->环绕后置通知,方法名:"+methodName+",参数:"+ Arrays.toString(args));
        }
        return result;
    }

12.5.2、配置环绕通知到切面

12、Spring之基于xml的AOP

            <!--
                aop:around标签:将方法设置为该切面的环绕通知(方法),效果等同于@Around注解
            -->
            <aop:around method="aroundMethod" pointcut-ref="pointcutOne"></aop:around>

12.5.3、测试使用效果

12、Spring之基于xml的AOP

注意:因为环绕通知包括了其他四种通知,所以一般要么配置其他四种通知,要么只配置环绕通知;
本示例为了展示效果才同时配置

    @Test
    public void testAOPByXML(){
        ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-aopByxml.xml");

        // 虽然不知道代理对象的类名,但可以通过代理对象和目标对象共同实现的接口类型来从ioc容器中获取代理对象
        Calculator calculator = ioc.getBean(Calculator.class);

        // 只能通过代理对象来访问目标对象中的方法
        calculator.div(1,1);

    }

12.6、切面的优先级

12.6.1、创建其他切面类ValidateAspect

12、Spring之基于xml的AOP

package org.rain.spring.aop.xml;

import org.springframework.stereotype.Component;

/**
 * @author liaojy
 * @date 2023/8/20 - 23:59
 */
// @Component注解:保证这个目标类能够放入IOC容器
@Component
public class ValidateAspect {
}

12.6.2、定义前置通知的功能

12、Spring之基于xml的AOP

    public void beforeMethod(){
        System.out.println("ValidateAspect-->前置通知");
    }

12.6.3、配置前置通知到切面

12、Spring之基于xml的AOP

        <aop:aspect ref="validateAspect">
            <aop:before method="beforeMethod" pointcut-ref="pointcutOne"></aop:before>
        </aop:aspect>

12.6.4、测试使用效果

12、Spring之基于xml的AOP

由控制台日志可知,ValidateAspect切面的前置通知方法生效了,但执行顺序在LoggerAspect切面的前置通知方法的后面

    @Test
    public void testAOPByXML(){
        ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-aopByxml.xml");

        // 虽然不知道代理对象的类名,但可以通过代理对象和目标对象共同实现的接口类型来从ioc容器中获取代理对象
        Calculator calculator = ioc.getBean(Calculator.class);

        // 只能通过代理对象来访问目标对象中的方法
        calculator.div(1,1);

    }

12.6.5、调整切面的优先级

12、Spring之基于xml的AOP

        <!--
           aop:aspect标签的order属性:用于设置切面的优先级,value属性值越小,优先级越高,默认值为Integer的最大值
        -->
        <aop:aspect ref="validateAspect" order="2023">
            <aop:before method="beforeMethod" pointcut-ref="pointcutOne"></aop:before>
        </aop:aspect>

12.6.6、测试调整后的效果

12、Spring之基于xml的AOP

由控制台日志可知,ValidateAspect切面的前置通知方法的执行顺序,在LoggerAspect切面的前置通知方法的前面

这是因为ValidateAspect切面的Order属性值已设为2023,要小于LoggerAspect切面所使用的默认值(Integer的最大值2147483647)文章来源地址https://www.toymoban.com/news/detail-661251.html

到了这里,关于12、Spring之基于xml的AOP的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring Boot入门(23):基于AOP实现自定义注解拦截接口日志并保存入库 | 超级详细,建议收藏

            在上两期中,我们着重介绍了如何集成使用 Logback 与 log4j2 日志框架的使用,今天我们讲解的主题依旧跟日志有关,不过不是使用何种开源框架,而是自己动手造。         Spring的核心之一AOP;AOP翻译过来叫面向切面编程, 核心就是这个切面. 切面表示从业务逻辑中

    2024年02月11日
    浏览(47)
  • Spring——事务注解@Transactional【建议收藏】

    在某些业务场景下,如果一个请求中,需要同时写入多张表的数据或者执行多条sql,为了保证操作的原子性(要么同时成功,要么同时失败),避免数据不一致的情况,我们一般都会用到事务;Spring框架下,我们经常会使用@Transactional注解来管理事务; 本篇介绍Spring的事务注

    2024年02月03日
    浏览(45)
  • Spring 中 @Bean 注解用法大全,建议收藏!

    将对象存储在 Spring 中,有两种注解类型可以实现: 类注解: @Controller 、 @Service 、 @Repository 、 @Component 、 @Configuration 方法注解: @Bean Spring Boot 基础就不介绍了,推荐看这个实战项目: https://github.com/javastacks/spring-boot-best-practice 如下使用 @Controller 存储Bean代码: 使用获取上

    2024年02月03日
    浏览(41)
  • Spring注解驱动开发之常用注解案例_告别在XML中配置Bean

    注解驱动开发就是不再使用Spring的bean.xml文件,改为纯使用注解的方式开发 @Configuration 此注解为配置类注解,相当于spring.xml文件,即配置类==配置文件 @Bean 给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id 示例 Person类(后续注解配置类中都会以此类举例),

    2024年01月21日
    浏览(49)
  • Mybatis基于注解与XML开发

    SpringBoot是一个基于Spring框架的快速开发的脚手架,它能够帮助我们开发者快速搭建项目环境,并提供了一些建议的配置方式,降低了开发者程序的开发和部署难度。 MyBatis是Java的持久化框架,目的是为了使操作数据库更加方便、灵活、高效。可以通过Java注解和XML文件来映射

    2024年02月15日
    浏览(41)
  • Aop基于xml和注解应用

    基于 XML 的 AOP 开发 问题1:在通知方法中如何定义切入点表达式? 问题2:如何配置切面? 问题3:在配置类上如何开启AOP注解功能? ①导入 AOP 相关坐标 ②创建目标接口和目标类(内部有切点) ③创建切面类(内部有增强方法) ④将目标类和切面类的对象创建权交给 spri

    2024年02月12日
    浏览(37)
  • Spring5学习随笔-高级注解(@ComponentScan、@Configuration.....),替换XML配置文件

    学习视频:【孙哥说Spring5:从设计模式到基本应用到应用级底层分析,一次深入浅出的Spring全探索。学不会Spring?只因你未遇见孙哥】 Spring在3.x提供的新的注解,用于替换XML配置文件。 问题 : 配置Bean在应用的过程中替换了XML具体的什么内容? AnnotationConfigApplicationContext 配

    2024年02月05日
    浏览(45)
  • Spring高手之路——深入理解注解驱动配置与XML配置的融合与区别

       XML 配置中,我们通常采用 ClassPathXmlApplicationContext ,它能够加载类路径下的 XML 配置文件来初始化 Spring 应用上下文。然而,在注解驱动的配置中,我们则使用以 Annotation 开头和 ApplicationContext 结尾的类,如 AnnotationConfigApplicationContext 。 AnnotationConfigApplicationContext 是 Spri

    2024年02月06日
    浏览(42)
  • Spring高手之路2——深入理解注解驱动配置与XML配置的融合与区别

       XML 配置中,我们通常采用 ClassPathXmlApplicationContext ,它能够加载类路径下的 XML 配置文件来初始化 Spring 应用上下文。然而,在注解驱动的配置中,我们则使用以 Annotation 开头和 ApplicationContext 结尾的类,如 AnnotationConfigApplicationContext 。 AnnotationConfigApplicationContext 是 Spri

    2024年02月08日
    浏览(51)
  • Spring CORS 跨域使用与原理(@CrossOrigin注解,Java配置类方式,xml方式)

    出于安全原因,浏览器禁止AJAX调用当前源之外的资源。 跨域资源共享(CORS)是由大多数浏览器实现的W3C规范,它允许您以一种灵活的方式指定授权哪种跨域请求,而不是使用一些不太安全、功能不太强大的hack(如IFrame或JSONP)。 Spring Framework 4.2 GA为CORS提供了一流的开箱即用支持

    2024年02月08日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包