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

SpringAop实战(xml文件/纯注解两种方式)

AOP的概述

什么是AOP?

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程
• AOP是一种编程范式,隶属于软工范畴,指导开发者如何组织程序结构
• AOP最早由AOP联盟的组织提出的,制定了一套规范.Spring将AOP思想引入到框架中,必须遵守AOP联盟的规范
• 通过预编译方式或者运行期动态代理实现程序功能的统一维护的一种技术
• AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型
• 利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率
AOP:面向切面编程.(思想.—解决OOP遇到一些问题)
AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码(性能监视、事务管理、安全检查、缓存)

AOP,可以在不修改源代码的前提下,对程序进行增强!

AOP的底层实现

JDK的动态代理技术

1、为接口创建代理类的字节码文件(.class文件)
2、使用ClassLoader类加载器将字节码文件加载到JVM
3、创建代理类实例对象(proxyObject),执行对象的目标方法

AOP的底层实现是动态代理,Spring框架的动态代理是基于JDK的接口动态代理(还有基于继承的cglib动态代理,有兴趣的读者可以自行学习)

接口实现的动态代理相比于单继承的cglib实现的动态代理更为灵活

AOP的优势

运行期间,不修改源代码的情况下对已有的方法进行增强
优势

  1. 减少重复的代码
  2. 提供开发的效率
  3. 维护方便

SpringAop的相关名词解释

Joinpoint(连接点)

所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点

Pointcut(切入点)

所谓切入点是指我们要对哪些Joinpoint进行拦截的定义(其实和连接点基本上是一回事,Pointcut = Joinpoint拦截

Advice(通知/增强)

所谓通知是指拦截到Joinpoint之后所要做的事情
通知分为
前置通知(如开启事务),
后置通知(如提交事务),
异常通知(如回滚事务),
最终通知(如关闭资源),
环绕通知(上面所有通知的集合体,但是需要自己完整写出环绕通知方法)

Target(目标对象)

代理的目标对象,也就是代理类对象代理的目标类对象

Weaving(织入)

是指把增强应用到目标对象来创建新的代理对象的过程

大白话就是代理类实现接口(重写的方法包含增强的部分)+ 创建代理类对象的过程

Proxy(代理)

一个类被AOP织入增强后,就产生一个结果代理类

Aspect(切面)

是切入点和通知的结合,以后咱们自己来编写和配置的(代理类)

AOP实战

以mysql的事务管理为例

1. 需要用到的maven依赖

以下依赖中,最重要的是AOP相关的依赖

<dependencies><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>log4j</groupId><artifactId>log4j</artifactId><version>1.2.12</version></dependency><!--有单元测试的环境,Spring5版本,Junit4.12版本--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!--连接池--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.10</version></dependency><!--mysql驱动包--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.6</version></dependency><!-- Spring整合Junit测试的jar包 --><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.0.2.RELEASE</version><scope>test</scope></dependency><!--AOP相关依赖--><!-- 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>

2. ApplicationContext.xml配置文件

引入具体的AOP的schema约束

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd”></beans>

3. 实体类,实体Dao,实体DaoImpl,实体对应的Service,Service对应的ServiceIImpl

mysql连接池模拟工具类TxUtils(因为我们要模拟的就是mysql的事务(提交/回滚),所以事务相关的原子方法需要我们独自实现)

真实开发场景下,我们要么使用Spring自带的事务管理机制,要么使用mybatis管理事务,不会这样赤裸裸地封装连接池

package com.qcby.mySpring03.utils;import com.alibaba.druid.pool.DruidDataSource;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;/*** 事务的工具类*/
public class TxUtils {private static DruidDataSource ds = null;// 使用ThreadLocal存储当前线程中的Connection对象private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();// 在静态代码块中创建数据库连接池static {try {ds = new DruidDataSource();ds.setDriverClassName("com.mysql.cj.jdbc.Driver");ds.setUrl("jdbc:mysql:///mybatis_demo?serverTimezone=UTC");ds.setUsername("root");ds.setPassword("980708");ds.setInitialSize(5);ds.setMaxActive(10);ds.setMaxWait(3000);} catch (Exception e) {throw new ExceptionInInitializerError(e);}}/*** @Method: getConnection* @Description: 从数据源中获取数据库连接* @Anthor:* @return Connection* @throws SQLException*/public static Connection getConnection() throws SQLException {// 从当前线程中获取ConnectionConnection conn = threadLocal.get();if (conn == null) {// 从数据源中获取数据库连接conn = getDataSource().getConnection();// 将conn绑定到当前线程threadLocal.set(conn);}return conn;}/*** @Method: startTransaction* @Description: 开启事务* @Anthor:**/public static void startTransaction() {try {Connection conn = threadLocal.get();if (conn == null) {conn = getConnection();// 把 conn绑定到当前线程上threadLocal.set(conn);}// 开启事务conn.setAutoCommit(false);} catch (Exception e) {throw new RuntimeException(e);}}/*** @Method: rollback* @Description:回滚事务* @Anthor:*/public static void rollback() {try {// 从当前线程中获取ConnectionConnection conn = threadLocal.get();if (conn != null) {// 回滚事务conn.rollback();}} catch (Exception e) {throw new RuntimeException(e);}}/*** @Method: commit* @Description:提交事务* @Anthor:*/public static void commit() {try {// 从当前线程中获取ConnectionConnection conn = threadLocal.get();if (conn != null) {// 提交事务conn.commit();}} catch (Exception e) {throw new RuntimeException(e);}}/*** @Method: close* @Description:关闭数据库连接(注意,并不是真的关闭,而是把连接还给数据库连接池)* @Anthor:**/public static void close() {try {// 从当前线程中获取ConnectionConnection conn = threadLocal.get();if (conn != null) {conn.close();// 解除当前线程上绑定connthreadLocal.remove();}} catch (Exception e) {throw new RuntimeException(e);}}/*** @Method: getDataSource* @Description: 获取数据源* @Anthor:* @return DataSource*/public static DataSource getDataSource() {// 从数据源中获取数据库连接return ds;}}

实体类Car

public class Car {private int id;private String carName;private int size;private String color;@Overridepublic String toString() {return "Car{" +"carName='" + carName + '\'' +", size=" + size +", color='" + color + '\'' +'}';}public Car(int id, String carName, int size, String color) {this.id = id;this.carName = carName;this.size = size;this.color = color;}public Car() {}public Car(String carName, int size, String color) {this.carName = carName;this.size = size;this.color = color;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getCarName() {return carName;}public void setCarName(String carName) {this.carName = carName;}public int getSize() {return size;}public void setSize(int size) {this.size = size;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}
}

CarDao接口

import java.sql.SQLException;
import java.util.List;public interface CarDao {List<Car> findAll();Car getById(Integer id);Integer insert(Car car) throws SQLException;Integer update(Car car);Integer delete(Integer id);}

CarDaoImpl实现类

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;@Repository("carDao")
public class CarDaoImpl implements CarDao {//    @Autowired
//    private DataSource dataSource;public List<Car> findAll() {//jdbc  查询数据库  拿到数据//1.加载驱动  连接池
//        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
//        dataSource.setUrl("jdbc:mysql:///spring_db");
//        dataSource.setUsername("root");
//        dataSource.setPassword("root");Connection conn = null;PreparedStatement stmt = null;ResultSet rs = null;List<Car> carList = new ArrayList<Car>();//2.获取连接对象try {conn = TxUtils.getConnection();//3.编写sqlString sql = "select * from car";//4.获取执行sql的stmt对象stmt = conn.prepareStatement(sql);//5.执行sqlrs = stmt.executeQuery();//6.遍历结果集while (rs.next()) {//实体类  account的实体类Car car = new Car();car.setId(rs.getInt("id"));car.setCarName(rs.getString("car_name"));car.setSize(rs.getInt("size"));car.setColor(rs.getString("color"));// 存储carList.add(car);}//7.关闭conn.close();stmt.close();rs.close();} catch (Exception e) {e.printStackTrace();}System.out.println("持久层:操作数据库保存订单");return carList;}public Car getById(Integer id) {return null;}public Integer insert(Car car) throws SQLException {Integer result = null;//jdbc  工具类实现获取连接 操作数据库  完成新增数据Connection connection = TxUtils.getConnection();// 编写sql语句String sql = "insert into car values (null,?,?,?)";// 预编译SQL语句PreparedStatement stmt = connection.prepareStatement(sql);// 设置值stmt.setString(1, car.getCarName());stmt.setInt(2, car.getSize());stmt.setString(3, car.getColor());// 执行操作result = stmt.executeUpdate();// 关闭资源 ,conn不能关闭stmt.close();return result;}public Integer update(Car car) {return null;}public Integer delete(Integer id) {return null;}
}

CarService接口

import java.sql.SQLException;
import java.util.List;public interface CarService {List<Car> findAll();void saveAll(Car car1, Car car2) throws SQLException;void saveAllTransaction(Car car1, Car car2);
}

CarServiceImpl实现类

package com.qcby.mySpring03.service.impl;import com.qcby.mySpring03.entity.Car;
import com.qcby.mySpring03.mapper.CarDao;
import com.qcby.mySpring03.service.CarService;
import com.qcby.mySpring03.utils.TxUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.sql.SQLException;
import java.util.List;@Service("carService")
public class CarServiceImpl implements CarService {@Autowiredprivate CarDao carDao;public void setCarDao(CarDao carDao) {this.carDao = carDao;}public List<Car> findAll() {return carDao.findAll();}// 不使用事务的情况下public void saveAll(Car car1, Car car2) throws SQLException {carDao.insert(car1);// 模拟异常// int a = 1 / 0;carDao.insert(car2);}public void saveAllTransaction(Car car1, Car car2) {try {// 开启事务TxUtils.startTransaction();// 保存1账号carDao.insert(car1);// 模拟异常int a = 1/0;// 保存2账号carDao.insert(car2);// 提交事务/回滚事务TxUtils.commit();} catch (Exception e) {// 打印异常信息e.printStackTrace();// 出现异常回滚事务TxUtils.rollback();} finally {// 关闭资源TxUtils.close();}}}

3.2 bean导入到ApplicationContext.xml中

 <bean id="carDao" class="com.qcby.mySpring03.mapper.impl.CarDaoImpl"/><bean id="carService" class="com.qcby.mySpring03.service.impl.CarServiceImpl"/>

4. 自定义切面类(切入点表达式+通知/增强方法实现);在ApplicationContext.xml中配置AOP

这一部分是最重要的

4.1 自定义切面类(切入点表达式+通知/增强方法实现)

// 自定义切面类
public class MyAspect {/*** 通知/增强的方法*/public void log() {// 发送手机短信// 发送邮件/记录日志/事务管理System.out.println("xml增强的方法执行了...");}
}
切入点表达式

切入点表达式的格式如下:

  • execution([修饰符] 返回值类型 包名.类名.方法名(参数))
  • 修饰符可以省略不写,不是必须要出现的。
  • 返回值类型是不能省略不写的,根据你的方法来编写返回值。可以使用 * 代替。
  • 包名例如:com.tx.demo3.BookDaoImpl
  • 首先com是不能省略不写的,但是可以使用*代替
  • 中间的包名可以使用 * 号代替
  • 如果想省略中间的包名可以使用*
  • 类名也可以使用 * 号代替,也有类似的写法:*DaoImpl
  • 方法也可以使用 * 号代替
  • 参数如果是一个参数可以使用 * 号代替,如果想代表任意参数使用 ..

举例,所有省略都不写的切入点表达式:

execution(public void com.qcby.mySpring03.service .impl.UserServiceImpl.findAll())

简写过后:
execution(* *.qcby.*.service .impl.*ServiceImpl.*(..))

AOP配置
<!--自定义切面类导入-->
<bean id="myAspect" class="com.qcby.mySpring03.aop.MyAspect"/>
<!--AOP配置-->
<aop:config><aop:aspect ref="myAspect"><aop:before method="log"pointcut="execution( * *.qcby.*.service.impl.*ServiceImpl.*(..))"/></aop:aspect></aop:config>
测试
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = {"classpath:ApplicationContext.xml"})
public class XmlAopTest {@Autowiredprivate UserService userService;@Autowiredprivate CarService carService;@Testpublic void xmlAopTest() {carService.findAll();}
}

运行结果

在这里插入图片描述

5. 纯注解AOP实战

通知类型注解
@Before—前置通知
@AfterReturing—后置通知
@Around—环绕通知(目标对象方法默认不执行的,需要手动执行)
@After—最终通知
@AfterThrowing—异常抛出通知

注解自定义切面类

@Component
@Aspect
public class MyAnnoAspect {/*** 通知*/@Before(value = "execution( * com.qcby.*.service.impl.*ServiceImpl.*(..))")public void startTransaction() {System.out.println("===前置通知执行:开启事务......");TxUtils.startTransaction();}@AfterReturning(value = "execution( * com.qcby.*.service.impl.*ServiceImpl.*(..))")public void commit() {System.out.println("===后置通知执行:提交事务......");TxUtils.commit();}@AfterThrowing(value = "execution( * com.qcby.*.service.impl.*ServiceImpl.*(..))")public void rollback() {System.out.println("===异常抛出通知执行:回滚事务......");TxUtils.rollback();}@After(value = "execution( * com.qcby.*.service.impl.*ServiceImpl.*(..))")public void close() {System.out.println("===最终通知执行:关闭资源......");TxUtils.close();}}

AOP配置类(开启AOP)

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration
@EnableAspectJAutoProxy
public class SpringAopConfig {
}

Spring扫描包配置类(顺便引入上一个配置类)

@Configuration
@ComponentScan("com.qcby")
@Import(value = {SpringAopConfig.class})
public class SpringJunit4Config {
}

在CarServiceImpl(@Service),CarDaoImpl(@Repository)上控制反转的注解,并配置各自的依赖注入的注解(@Autowired)

@Service("carService")
public class CarServiceImpl implements CarService {@Autowiredprivate CarDao carDao;
@Repository("carDao")
public class CarDaoImpl implements CarDao {// 	有连接池工具类就不需要注入DataSource了
//    @Autowired
//    private DataSource dataSource;

测试

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import java.sql.SQLException;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringJunit4Config.class)
public class TransactionTest {@Autowiredprivate CarService carService;@Testpublic void shiwuTest() throws SQLException {Car car1 = new Car("car1", 100, "green");Car car2 = new Car("car2", 100, "yellow");carService.saveAll(car1, car2);}
}

由于存在除0异常,所以事务应该会回滚

在这里插入图片描述

执行结果

出现除0异常,事务回滚
在这里插入图片描述
没有出现异常,事务提交

在这里插入图片描述

相关文章:

SpringAop实战(xml文件/纯注解两种方式)

AOP的概述 什么是AOP&#xff1f; 在软件业&#xff0c;AOP为Aspect Oriented Programming的缩写&#xff0c;意为&#xff1a;面向切面编程 • AOP是一种编程范式&#xff0c;隶属于软工范畴&#xff0c;指导开发者如何组织程序结构 • AOP最早由AOP联盟的组织提出的,制定了…...

(八)Linux的进程与线程

多任务处理是指用户可以在同一时间内运行多个应用程序,每个正在执行的程序被称为一个任务。一个任务包含一个或多个完成独立功能的子任务,其中子任务可以是进程或线程。Linux就是一个支持多任务的操作系统,比起单任务系统它的功能增强许多。 一.进程 进程:一个具有独立功…...

Map-JAVA面试常问

1.HashMap底层实现 底层实现在jdk1.7和jdk1.8是不一样的 jdk1.7采用数组加链表的方式实现 jdk1.8采用数组加链表或者红黑树实现 HashMap中每个元素称之为一个哈希桶(bucket),哈希桶包含的内容有以下4项 hash值&#xff08;哈希函数计算出来的值&#xff09; Key value next(…...

prometheus+grafana搭建监控系统

1.prometheus服务端安装 1.1下载包 使用wget下载 &#xff08;也可以直接去官网下载包Download | Prometheus&#xff09; wget https://github.com/prometheus/prometheus/releases/download/v2.44.0/prometheus-2.44.0.linux-amd64.tar.gz1.2解压 tar xf prometheus-2.44…...

flink学习-flink sql

动态表 在flink的数据处理中&#xff0c;数据流是源源不断的&#xff0c;是无界的&#xff0c;所以对于flink处理的数据表是一张动态表&#xff0c;所以对于动态表的查询也是持续的&#xff0c;每接收一条新数据会进行一次新的查询。 持续查询 因为数据在一直源源不动的到来…...

高考填报志愿攻略,5个步骤选专业和院校

在高考完毕出成绩的时候&#xff0c;很多人会陷入迷茫中&#xff0c;好像努力了这么多年&#xff0c;却不知道怎么规划好未来。怎么填报志愿合适&#xff1f;在填报志愿方面有几个内容需要弄清楚&#xff0c;按部就班就能找到方向&#xff0c;一起来了解一下正确的步骤吧。 第…...

Kubernetes排错(十)-处理容器数据磁盘被写满

容器数据磁盘被写满造成的危害: 不能创建 Pod (一直 ContainerCreating)不能删除 Pod (一直 Terminating)无法 exec 到容器 如何判断是否被写满&#xff1f; 容器数据目录大多会单独挂数据盘&#xff0c;路径一般是 /var/lib/docker&#xff0c;也可能是 /data/docker 或 /o…...

使用QtGui显示QImage的几种方法

问题描述 我是一名刚学习Qt的新手,正在尝试创建一个简单的GUI应用程序。当点击一个按钮时,显示一张图片。我可以使用QImage对象读取图片,但是否有简单的方法调用一个Qt函数,将QImage作为输入并显示它? 方法一:使用QLabel显示QImage 最简单的方式是将QImage添加到QLabe…...

C++ lamda

1 lamada 的函数指针存在哪里&#xff1f;需要通过分析编译后的二进制&#xff1b; 2 捕获了什么&#xff1f; 为什么捕获&#xff1f;捕获的范围是什么&#xff1f; 捕获的生命周期是什么&#xff1f; lambda 定义匿名函数&#xff0c;使得代码更加灵活简洁&#xff1b; lam…...

Linux_应用篇(27) CMake 入门与进阶

在前面章节内容中&#xff0c;我们编写了很多示例程序&#xff0c;但这些示例程序都只有一个.c 源文件&#xff0c;非常简单。 所以&#xff0c;编译这些示例代码其实都非常简单&#xff0c;直接使用 GCC 编译器编译即可&#xff0c;连 Makefile 都不需要。但是&#xff0c;在实…...

51单片机STC89C52RC——8.1 8*8 LED点阵模块(点亮一个LED)

目录 目的/效果 一&#xff0c;STC单片机模块 二&#xff0c;8*8 LED点阵模块 2.1 电路图 2.1.1 8*8 点阵模块电路图 2.1.2 74HC595&#xff08;串转并&#xff09;模块 电路图 2.1.3 芯片引脚 2.2 引脚电平分析 2.3 74HC595 串转并模块 2.3.1 装弹&#xff08;移位…...

2024最新免费版轻量级Navicat Premium Lite 下载和安装教程

2024最新免费版轻量级Navicat Premium Lite 下载和安装教程 关于猫头虎 大家好&#xff0c;我是猫头虎&#xff0c;别名猫头虎博主&#xff0c;擅长的技术领域包括云原生、前端、后端、运维和AI。我的博客主要分享技术教程、bug解决思路、开发工具教程、前沿科技资讯、产品评…...

PHP+laravel 生成word

此功能较为繁琐我会从源头讲起 首先是数据库设置&#xff0c;下面是我的数据库结构 合同模版表 CREATE TABLE contract_tpl (id bigint unsigned NOT NULL AUTO_INCREMENT,name varchar(191) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 合同名称,file varchar(191) COLL…...

redis集群简单介绍及其搭建过程

Redis集群 1、哨兵模式 哨兵可以有多个&#xff0c;从服务器也可以有多个&#xff0c;从服务器也可以有多个&#xff0c;在Redis3.0以前的版本要实现集群一般是借助哨兵sentinel工具来监控master节点的状态&#xff0c;如果master节点异常&#xff0c;则会实现主从切换&#x…...

linux桌面运维----第五天

1、创建用户命令useradd&#xff1a; 作用&#xff1a;创建用户 ​语法&#xff1a;useradd [选项名] 用户名 ​选项&#xff1a; -d<登入目录> 指定用户登入时的起始目录。 【掌握】 -g<群组> 指定用户所属的群组&#xff08;基本组&#xff09;。【掌握】…...

【SQL Server数据库】简单查询

目录 用SQL语句完成下列查询。使用数据库为SCHOOL数据库 1. 查询学生的姓名、性别、班级名称&#xff0c;并把结果存储在一张新表中。 2. 查询男生的资料。 3. 查询所有计算机系的班级信息。 4&#xff0e;查询艾老师所教的课程号。 5. 查询年龄小于30岁的女同学的学号和姓名。…...

Docker 从入门到精通(大全)

一、概述 1.1 基本概念 Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言 并遵从 Apache2.0 协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上&#xff0c;也可以实现虚拟化。…...

基于JSP的在线教育资源管理系统

开头语&#xff1a; 你好呀&#xff0c;我是计算机学长猫哥&#xff01;如果你对在线教育资源管理系统感兴趣或者有相关需求&#xff0c;欢迎在文末找到我的联系方式。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;JSP技术 工具&#xff1a;IDE、N…...

在java中代理http请求,如何避免陷入循环?

在 Java 中&#xff0c;代理 HTTP 请求时&#xff0c;如果不小心配置不当&#xff0c;可能会导致循环请求。循环请求通常发生在代理服务器将请求再次发送回自己&#xff0c;形成一个死循环。为了避免这种情况&#xff0c;可以采取以下几种方法&#xff1a; 将域名设置为指定的…...

国内镜像源网址

腾讯&#xff1a;腾讯软件源 (tencent.com) 阿里&#xff1a;阿里巴巴开源镜像站-OPSX镜像站-阿里云开发者社区 (aliyun.com) 清华&#xff1a;清华大学开源软件镜像站 | Tsinghua Open Source Mirror...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

基于Java+MySQL实现(GUI)客户管理系统

客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息&#xff0c;对客户进行统一管理&#xff0c;可以把所有客户信息录入系统&#xff0c;进行维护和统计功能。可通过文件的方式保存相关录入数据&#xff0c;对…...