Spring基于XML文件配置AOP

AOP

AOP,面向切面编程,是对面向对象编程OOP的升华。OOP是纵向对一个事物的抽象,一个对象包括静态的属性信息,包括动态的方法信息等。而AOP是横向的对不同事物的抽象,属性与属性、方法与方法、对象与对象都可以组成一个切面,而用这种思维去设计编程的方式叫做面向切面编程

AOP思想的实现方案:动态代理技术,在运行期间,对目标对象的方法进行增强,代理对象同名方法内可以执行原有逻辑的同时嵌入执行其他增强逻辑或其他对象的方法

下面是AOP的实现思想

创建增强类,编写前方法与后方法

public class MyAdvice {
    public void beforeAdvice(){
        System.out.println("执行增强前方法");
    }

    public void afterAdvice(){
        System.out.println("执行增前后方法");
    }
}

编写被增强类,并编写一个方法用于增强

public class UserServiceImpl implements UserService {

    @Override
    public void show() {
        System.out.println("show...");
    }

}

Bean后处理器去实现将Bean对象替换成代理类

public class MyBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {
    private ApplicationContext context;

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        //对指定方法进行增强
        if (bean instanceof UserService) {
            //获取增强方法
            MyAdvice myAdvice = context.getBean(MyAdvice.class);
            Object proxyInstance = Proxy.newProxyInstance(bean.getClass().getClassLoader(),
                    bean.getClass().getInterfaces(),
                    new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            myAdvice.beforeAdvice();
                            method.invoke(bean, args);
                            myAdvice.afterAdvice();
                            return proxy;
                        }
                    });
            return proxyInstance;
        }
        return bean;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }
}

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"
  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">

  <bean id="userService" class="com.zmt.service.impl.UserServiceImpl"></bean>
  <bean class="com.zmt.processor.MyBeanPostProcessor"/>
  <bean class="com.zmt.advice.MyAdvice"/>
</beans>

执行测试代码

public class ApplicationTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        UserService userService = context.getBean(UserService.class);
        userService.show();
    }
}

执行结果如下 

这种实现方式存在两个问题,一个是需要被增强的Bean对象需要硬编码指定,其次是增强方法也是被写死的,如果需要修改被增强的类或是修改增强方法都需要修改代码。

那么我们在了解Spring中AOP时,需要先了解如下几个概念

目标对象

Taeget

被增强的方法所在的对象

代理对象

Proxy

对目标方法进行增强后的对象,客户端实际调用的对象

连接点

Joinpoint

目标对象中可以被增强的方法

切入点

Pointcut

目标对象中实际被增强的方法

通知\增强

Advice

增强部分的代码逻辑

切面

Aspect

增强和切入点的组合

织入

Weaving

将通知和切入点动态组合的过程

那么接下来给出基于XML的实现AOP的示例代码

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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
       http://www.springframework.org/schema/aop
       https://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="userService" class="com.zmt.service.impl.UserServiceImpl"/>
    <!--将增强类交给Spring管理-->
    <bean id="myAdvice" class="com.zmt.advice.MyAdvice"/>
    <aop:config>
        <!--配置切面表达式,指定需要被增强的方法-->
        <aop:pointcut id="myPointcut" expression="execution(void com.zmt.service.impl.UserServiceImpl.show())"/>
        <!--指定切点与哪些增强类结合-->
        <aop:aspect ref="myAdvice">
            <aop:before method="beforeAdvice" pointcut-ref="myPointcut"/>
        </aop:aspect>
    </aop:config>
</beans>
public class UserServiceImpl implements UserService {

    @Override
    public void show() {
        System.out.println("show...");
    }

}
public class MyAdvice {
    public void beforeAdvice(){
        System.out.println("执行增强前方法");
    }

    public void afterAdvice(){
        System.out.println("执行增前后方法");
    }
}

测试代码如下

public class ApplicationTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        UserService userService = context.getBean(UserService.class);
        userService.show();
    }
}

运行结果如下

execution语法

execution([访问修饰符] 返回值类型 报名.类名.方法名(参数))

  • 访问修饰符可以省略不写
  • 返回值类型、某一级包名、类名、方法名可以使用 * 表示任意
  • 包名与类名之间使用单点 . 表示该包下的类,使用双点 .. 表示该包以及子包下的类
  • 参数列表可以使用双点 .. 表示任意参数

XML文件下通知的配置类型

通知名称

配置方式

执行时机

前置通知

< aop:before >

目标方法执行之前执行

后置通知

< aop:after-returning >

目标方法执行之后执行,目标方法异常时不再执行

环绕通知

< aop:around >

目标方法执行前后执行,目标方法异常时,环绕后方法不再执行

异常通知

< aop:after-throwing >

目标方法抛出异常时执行

最终通知

< aop:after >

不管目标方法是否有异常,最终都会执行

环绕通知需要将连接点传入,具体的增强类实现代码如下

public class MyAdvice {
    public void beforeAdvice(){
        System.out.println("执行增强前方法");
    }

    public void afterAdvice(){
        System.out.println("执行增前后方法");
    }

    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕前通知。。。");
        Object proceed = joinPoint.proceed();
        System.out.println("环绕后通知。。。");
        return proceed;
    }
}

增强方法在被调用时,Spring可以为其传递一些必要参数

参数类型

作用

JoinPoint

连接点对象,任何通知都可以使用,可以获取当前目标对象,目标方法参数等信息

ProceedingJoinPoint

JoinPoint子类对象,主要是在环绕通知中执行proceed(),进而执行目标方法

Throwable

异常对象,使用在异常通知中,需要在配置文件中指出异常对象名称

除了上面实现AOP之外,基于XML文件配置的实现方式还存在另一种实现方式,通过实现接口来表示该增强类的具体操作。

public class MyAdvice2 implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("环绕前通知。。。。");
        Object res = invocation.getMethod().invoke(invocation.getThis(), invocation.getArguments());
        System.out.println("环绕后通知。。。。");
        return res;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:aop="http://www.springframework.org/schema/aop"
  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
  http://www.springframework.org/schema/aop
  https://www.springframework.org/schema/aop/spring-aop.xsd">

  <bean id="userService" class="com.zmt.service.impl.UserServiceImpl"/>

  <bean id="myAdvice2" class="com.zmt.advice.MyAdvice2"/>
  <aop:config>
    <aop:pointcut id="myPointcut" expression="execution(void com.zmt.service.impl.UserServiceImpl.show())"/>
    <!-- 指定增强类与切点 -->
    <aop:advisor advice-ref="myAdvice2" pointcut-ref="myPointcut"/>
  </aop:config>
</beans>

注意:一个增强类可以实现多个Advice接口

AOP配置的两种语法形式不同点

语法形式不同:

  • advisor是通过实现接口来确认通知的类型
  • aspect是通过配置确认通知的类型,更加灵活

可配置的切面数量不同:

  • 一个advisor只能配置一个固定通知和一个切点表达式
  • 一个aspect可以配置多个通知和多个切点表达式任意组合

使用场景不同:

  • 允许随意搭配情况下可以使用aspect进行配置
  • 如果通知类型单一、切面单一的情况下可以使用advisor进行配置
  • 在通知类型已经固定,不用人为指定通知类型时,可以使用advisor进行配置

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/232460.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

nginx多端口部署

1.配置nginx.conf文件 有几个端口需要部署就写几个server&#xff0c;我这里只部署了两个端口分别为80和81端口&#xff0c;所以有两个server文件。80端口项目入口在根目录的test文件中&#xff0c;81端口项目入口在根目录的test1文件夹中。 2.准备项目文件html文件 在/test1…

【干货分享】KingIOServer与三菱PLC的通讯的应用案例

哈喽&#xff0c;大家好&#xff0c;我是雷工&#xff01; 最近一个项目涉及用KingIOServer采集三菱PLC数据&#xff0c;特记录通讯过程方便备忘。 一、版本说明&#xff1a; 1、KingIOServer版本&#xff1a;3.7SP2 2、PLC型号&#xff1a;Q03UDV 和Q03UDE自带以太网网口。…

智能优化算法应用:基于蝗虫算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于蝗虫算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于蝗虫算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.蝗虫算法4.实验参数设定5.算法结果6.参考文献7.MA…

Linux下apisix离线安装教程

Linux下apisix离线安装教程 一、首先需要安装etcd&#xff1a;二、通过rpm离线安装apisix三、启动apisix四、安装apisix-dashboard1、安装2、更改dashboard登录账号名和密码3、运行 一、首先需要安装etcd&#xff1a; 解压缩etcd后执行以下命令&#xff1a; tar -xvf etcd-v3.…

【QT】QComboBox和QPlainTextEdit基本介绍和应用示例

目录 1.QComboBox 1.1 QComboBox概述 1.2 QComboBox信号 1.3 QComboBox常用功能 1.4 QComboBox添加简单项 1.6 QComboBox列表项的访问 2.QPlainTextEdit 2.1 QPlainTextEdit概述 2.2 QPlainTextEdit的基本属性 2.3 QPlainTextEdit的公共函数 2.4 QPlainTextEdit的公…

【开源】基于Vue和SpringBoot的音乐偏好度推荐系统

项目编号&#xff1a; S 012 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S012&#xff0c;文末获取源码。} 项目编号&#xff1a;S012&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、系统设计2.1 功能模块设计2.1.1 音乐档案模块2.1…

单臂路由与三层交换机

单臂路由 划分VLAN后同一VLAN的计算机属于同一个广播域&#xff0c;同一VLAN的计算机之间的通信是不成问题的。然而&#xff0c;处于不同VLAN的计算机即使是在同一交换机上&#xff0c;它们之间的通信也必须使用路由器。 图&#xff08;a&#xff09;是一种实现VLAN间路由的方…

Java编程中通用的正则表达式(二)

正则表达式&#xff0c;又称正则式、规则表达式、正规表达式、正则模式或简称正则&#xff0c;是一种用来匹配字符串的工具。它是一种字符串模式的表示方法&#xff0c;可以用来检索、替换和验证文本。正则表达式是一个字符串&#xff0c;它描述了一些字符的组合&#xff0c;这…

网络互连与常用设备

网络互连是为了将两个以上具有独立自治能力、同构或异构的计算机网络连接起来&#xff0c;实现数据流通&#xff0c;扩大资源共享的范围&#xff0c;或者容纳更多的用户。网络互连包括局域网与局域网的互连、局域网与广域网的互连、广域网与广域网的互连&#xff0c;这可以扩大…

【漏洞复现】华脉智联指挥调度平台命令执行漏洞

Nx01 产品简介 深圳市华脉智联科技有限公司&#xff0c;融合通信系统将公网集群系统、专网宽带集群系统、不同制式、不同频段的短波/超短波对讲、模拟/数字集群系统、办公电话系统、广播系统、集群单兵视频、视频监控系统、视频会议系统等融为一体&#xff0c;集成了专业的有线…

Python 从入门到精通 学习笔记 Day03

Python 从入门到精通 第三天 今日目标 流程控制语句、退出循环、练习学习的内容 一、流程控制语句 流程控制的三种方式&#xff1a;顺序语句、双分支语句、循环语句 双分支语句 Python 的双分支语句使用if-else语句实现。 其语法结构如下: if条件:#如果条作为真&#xff…

二十一章总结

网络程序设计基础 局域网与互联网 为了实现两台计算机的通信&#xff0c;必须用一个网络线路连接两台计算机。如下图所示 网络协议 1.IP协议 IP是Internet Protocol的简称&#xff0c;是一种网络协议。Internet 网络采用的协议是TCP/IP协议&#xff0c;其全称是Transmission…

Mybatis XML增删操作(结合上文)

先来"增"操作 在UserInfoXMLMapper.xml里面写 <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <…

【小红书运营指南1】赛道选择 + 账号运营全周期

小红书运营指南1 写在最前面11.23标签一级标签二级标签 网络资源整理1. 赛道选择近2年小红书女性人群画像 2. 基础认知阶段3. 账号启动阶段4. 选题规划阶段5. 爆款打造阶段6. 涨粉变现阶段涨粉变现阶段粉丝发展阶段 写在最前面 最近做的一个项目调研&#xff0c;调研和实际有一…

Docker网络架构介绍

本文主要介绍了Docker容器的单机网络架构与集群网络架构&#xff0c;辅以演示&#xff0c;并简单介绍了网络管理中的命令。 前文&#xff1a; Docker的安装与简单操作命令-CSDN博客 docker网络原理介绍 与ovs类似&#xff0c;docker容器采用veth-pair linux bridge (虚拟交…

LabelImg的使用及注意事项

LabelImg是一款开源的图像标注工具&#xff0c;它主要用于标注目标检测、语义分割和图像分类等深度学习中需要的数据集。通过使用LabelImg&#xff0c;用户可以快速、准确地为图片中的目标添加标注信息&#xff0c;从而建立数据集。 使用步骤&#xff1a; 下载LabelImg&#x…

[Linux] Apache的配置与运用

一、web虚拟主机的构台服务器上运行多个网站&#xff0c;每个网站实际上并不独立占用整个服务器&#xff0c;因此称为"虚拟"虚拟主机的虚拟主机服务可以让您充分利用服务器的硬件资源&#xff0c;大大降低了建立和运营网站的成本 Httpd服务使构建虚拟主机服务器变得容…

MyBatis——Java 持久层框架

文章目录 MyBatis 是什么准备工作创建一个数据库和表引入依赖 配置连接字符串和 MyBatisMyBatis 组成MyBatis 使用步骤定义一个类创建 MyBatis 接口&#xff08;以查询所有为例&#xff09;创建与接口对应的 xml 文件&#xff08;实现接口中的所有方法&#xff09;使用单元测试…

[面试题~k8s] 云原生必问基础篇

文章目录 概念篇1. k8s 是什么2. Container3. Pod4. Node5. Namespace6. Service7. Label8. Replica Set&#xff08;副本集)9. Deployment10. Volume11. Namespace12. PV 和 PVC 基础篇1. 删除 pod 流程2. k8s 有哪些组件master nodeworker node 3. k8s 和 docker 的关系4. 简…

Java网络编程——通过JDBC API访问数据库

关系数据库仍然是目前最流行的数据库系统。如果没有特别说明&#xff0c;本帖所说的数据库就都指关系数据库。关系数据库中最主要的数据结构是表&#xff0c;表用主键来标识每一条记录&#xff0c;表与表之间可以存在外键参照关系。数据库服务器提供管理数据库的各种功能&#…