当前位置: 首页 > news >正文

Spring框架(AOP)

面向对象编程:调用对象中的方法属性。 --》对象是堆中的一块内存空间,包含方法、全局变量。

面向切面编程(AOP):不改变原有代码,直接把要增加的功能的代码切入进去。

AOP相关术语

  • 连接点:类里面可以被增强的方法被称为连接点。
  • 增强:对原有方法进行增强。
  • 切入点:实际被增强的方法就是切入点。
  • 通知:实际被增强的逻辑叫做通知(增强)。
    • 通知的类型:
      • 前置通知(在判断方法之前通知)、后置通知(在判断方法之后通知,切入点方法异常不执行)、环绕通知(在判断方法前、后通知)、异常通知(在判断方法出现异常的情况下通知)、最终通知(无论切入点方法是否出现异常都会通知)。
    • 注:方法指的是切入点。
  • 切面:一个动作,将通知切入到切入点方法的过程

XML配置方式实现

导入相关依赖(pom.xml)

<dependencies>
<!--Spring框架--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency><!--测试--><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.0.2.RELEASE</version></dependency><!--日志--><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.12</version></dependency><!--测试单元  @Test来自junit--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!--AOP联盟--><dependency><groupId>aopalliance</groupId><artifactId>aopalliance</artifactId><version>1.0</version></dependency><!--Spring Aspects--><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.0.2.RELEASE</version></dependency><!--aspectj  面向切面的开源框架--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.3</version></dependency></dependencies>

创建Demo类(被增强类)

//Demo类中所有方法都可以作为切入点,此处我们选择insert()作为切入点
public class Demo {public void add(String name,int age){System.out.println("add--------------");}public void delete(String name,int age){System.out.println("delete--------------");}public void update(String name,int age){System.out.println("update--------------");}//在插入之前验证name和agepublic void insert(String name,int age){System.out.println("insert--------------");}
}

创建DemoProxy类(增强类)

public class DemoProxy {public void judge(){System.out.println("对name和age进行验证......");}
}

配置Spring.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="demo" class="com.qcby.Demo"/><!--驼峰命名--><bean id="demoProxy" class="com.qcby.DemoProxy"/><!--直接进行配置--><!--配置切面--><aop:config><aop:aspect ref="demoProxy"><!--前置通知--><!--pointcut后是切入点--><!--insert(..) 中(..)表示参数,没有参数括号中不用写--><aop:before method="judge" pointcut="execution(public void com.qcby.Demo.insert(..))"/></aop:aspect></aop:config>
</beans>

测试代码

public class DemoTest {@Testpublic void run(){ApplicationContext context = new ClassPathXmlApplicationContext("Spring.xml");Demo demo = (Demo) context.getBean("demo");demo.insert("张三",18);}
}

测试结果

四种通知实现在Spring.xml中的配置

通知类型执行时机
前置通知(@Before)在切入点方法执行之前执行
后置通知(@AfterReturning)在切入点方法正常执行后执行(异常时不执行)
环绕通知(@Around)在切入点方法执行前后执行(功能最强大的通知类型)
异常通知(@AfterThrowing)在切入点方法抛出异常时执行
最终通知(@After)无论切入点方法是否出现异常都会执行(类似finally块)
<?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="demo" class="com.qcby.Demo"/><!--驼峰命名--><bean id="demoProxy" class="com.qcby.DemoProxy"/><!--直接进行配置--><!--配置切面--><aop:config><aop:aspect ref="demoProxy"><!--前置通知--><!--pointcut后是切入点--><!--insert(..) 中(..)表示参数,没有参数括号中不用写-->
<!--            <aop:before method="judge" pointcut="execution(public void com.qcby.Demo.insert(..))"/>--><!--最终通知-->
<!--            <aop:after method="judge" pointcut="execution(public void com.qcby.Demo.insert(..))"/>--><!--环绕通知-->
<!--            <aop:around method="judge" pointcut="execution(public void com.qcby.Demo.insert(..))"/>--><!--异常通知-->
<!--            <aop:after-throwing method="judge" pointcut="execution(public void com.qcby.Demo.insert(..))"/>--><!--后置通知-->
<!--            <aop:after-returning method="judge" pointcut="execution(public void com.qcby.Demo.insert(..))"/>--></aop:aspect></aop:config>
</beans>

其中环绕通知需要在DemoProxy中进行配置

public class DemoProxy {public void judge(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("对name和age进行验证......,在insert()执行前");//执行切入点proceedingJoinPoint.proceed();System.out.println("对name和age进行验证......,在insert()执行后");}
}

利用注解的方式实现AOP

Demo类整体不变(面向切面编程不会对该类中的代码进行改动,只需在类中加上注解@Service或@Controller表明能够生成bean对象)

Spring.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"xmlns:context="http://www.springframework.org/schema/context"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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!--开启注解扫描--><context:component-scan base-package="com.qcby"/><!--开启Aspect生成代理对象  第三方工具--><aop:aspectj-autoproxy/>
</beans>

DemoProxy

package com.qcby;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;@Service
@Aspect  //表示是增强类
public class DemoProxy {//环绕通知//@Around(value = "execution(public void com.qcby.Demo.insert(..))")public void judge(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("对name和age进行验证......,在insert()执行前");//执行切入点proceedingJoinPoint.proceed();System.out.println("对name和age进行验证......,在insert()执行后");}//前置通知@Before(value = "execution(public void com.qcby.Demo.insert(..))")public void Ajudge() throws Throwable {System.out.println("对name和age进行验证");}//最终通知//@After(value = "execution(public void com.qcby.Demo.insert(..))")public void Bjudge() throws Throwable {System.out.println("对name和age进行验证");}//异常通知//@AfterThrowing(value = "execution(public void com.qcby.Demo.insert(..))")public void Cjudge() throws Throwable {System.out.println("对name和age进行验证");}//后置通知//@AfterReturning(value = "execution(public void com.qcby.Demo.insert(..))")public void Djudge() throws Throwable {System.out.println("对name和age进行验证");}
}

测试结果如下(以前置通知为例)

http://www.lryc.cn/news/622949.html

相关文章:

  • “openfeign“调用接口上传文件报错:Failed to deleted temporary file used for part [file]
  • 博士招生 | 香港大学 机器增强认知实验室 招收博士生/实习生/访问学生
  • 安卓11 12系统修改定制化_____修改系统默认域名解析规则 实现屏蔽广告 屏蔽应用更新等功能
  • CVE-2021-4300漏洞复现
  • css实现圆角+边框渐变+背景半透明
  • Camera相机人脸识别系列专题分析之十九:MTK ISP6S平台FDNode原生代码
  • 34 HTB Cat 机器 - 中等难度
  • Three.js三大组件:场景(Scene)、相机(Camera)、渲染器(Renderer)
  • GitHub PR 提交流程
  • 防火墙虚拟系统配置实验
  • 平滑方法(smoothing)
  • SpringBoot自动配置原理(二)
  • 算法训练营day53 图论④ 110.字符串接龙、105.有向图的完全可达性、106.岛屿的周长
  • 记与客户端的一次“无谓之争”
  • 算法训练营day52 图论③ 101.孤岛的总面积、102.沉没孤岛、103.水流问题、104.建造最大岛屿
  • UniApp 页面传参方式详解
  • 数据结构——单链表oj(续)
  • RK3568 NPU RKNN(五):RKNN-ToolKit-lite2板端推理
  • 企业级Java项目金融应用领域——银行系统(补充)
  • 小白挑战一周上架元服务——元服务开发06
  • 24. async await 原理是什么,会编译成什么
  • 硬核北京 | 2025世界机器人大会“破圈”,工业智能、康养科技…… 亦庄上演“机器人总动员”
  • 石头科技披露半年报:营收79.03亿元,同比大增78.96%
  • 5 索引的操作
  • 强化学习入门教程(附学习文档)
  • 我的世界Java版1.21.4的Fabric模组开发教程(十九)自定义生物群系
  • 小迪安全v2023学习笔记(六十三讲)—— JS加密断点调试
  • 【图论】分层图 / 拆点
  • 什么是模型预测控制?
  • Windows MCP.Net:革命性的 .NET Windows 桌面自动化 MCP 服务器