Spring之bean的生命周期
目录
1.Bean的初始化过程
1.1代码详解
1.2思考
2.Bean的单例与多例选择
2.1论证单例与多例优缺点
2.2论证初始化时间点
2.3个例演示
Spring Bean的生命周期:
一、通过XML、Java annotation(注解)以及Java Configuration(配置类),等方式加载Spring Bean
二、BeanDefinitionReader:解析Bean的定义。在Spring容器启动过程中,会将Bean解析成Spring内部的BeanDefinition结构;理解为:将spring.xml中的<bean>标签转换成BeanDefinition结构(有点类似于XML解析)
三、BeanDefinition:包含了很多属性和方法。例如:id、class(类名)、scope、ref(依赖的bean)等等。其实就是将bean(例如<bean>)的定义信息
存储到这个对应BeanDefinition相应的属性中
四、BeanFactoryPostProcessor:是Spring容器功能的扩展接口。
注意:
1)BeanFactoryPostProcessor在spring容器加载完BeanDefinition之后,
在bean实例化之前执行的
2)对bean元数据(BeanDefinition)进行加工处理,也就是BeanDefinition
属性填充、修改等操作
五、BeanFactory:bean工厂。它按照我们的要求生产我们需要的各种各样的bean。
六、Aware感知接口:在实际开发中,经常需要用到Spring容器本身的功能资源
例如:BeanNameAware、ApplicationContextAware等等
BeanDefinition 实现了 BeanNameAware、ApplicationContextAware
七、BeanPostProcessor:后置处理器。在Bean对象实例化和引入注入完毕后,
在显示调用初始化方法的前后添加自定义的逻辑。(类似于AOP的绕环通知)
前提条件:如果检测到Bean对象实现了BeanPostProcessor后置处理器才会执行
Before和After方法
BeanPostProcessor
1)Before
2)调用初始化Bean(InitializingBean和init-method,Bean的初始化才算完成)
3)After
完成了Bean的创建工作
八、destory:销毁
1.Bean的初始化过程
1.xml/annotation/configuation/配置JavaBean
2.BeanDefinitionReader解析配置的JavaBean得到Beandefinition,最终得到List<BeanDefinition>集合
3.触发BeanFactoryPostProcessor,在JavaBean初始化之前执行
4.Spring中的BeanFactory,会通过List<BeanDefinition>集合遍历初始化所有的JavaBean对象
5.如果自己的JavaBean需要调动Spring上下文中的资源(方法或属性),那么需要实现*Aware感知接口
6.如果自己的JavaBean已经初始化好了,还需扩展功能,那么需要借助BeanPostProcessor后置处理器来实现
具体图解与流程图如下:
1.1代码详解
BeanFactoryPostProcessor是Spring容器功能的扩展接口,怎么理解?比如假设我们现在有一个内部类Person,其原本有三个属性。BeanFactoryPostProcessor的作用就是可以在初始化对象之前可以做一个补充,它内部类原本只有三个属性,我们可以给它加一个关联属性User进去,并对新增的关联属性User对象做出相对应的处理,具体代码详解如下:
package com.kissship.beanlife;/*** @author Kissship* @site www.Kissship.com* @company xxx公司* @create 2023-08-18-14:17*/
public class Demo1 {public static void main(String[] args) {
// BeanDefinition}
}class User{
//无值
}
class Person{private int pid;private String name;private String sex;private User user;//扩展新增的关联属性(无值)public int getPid() {return pid;}public void setPid(int pid) {this.pid = pid;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public Person() {}//在初始化对象之前可以做一个补充,比如上面原本只有三个属性,我们也可以给它加一个关联属性Userpublic Person(int pid, String name, String sex) {this.init();//扩展的内容this.pid = pid;this.name = name;this.sex = sex;}//这里可以针对我们新增的关联属性User对象作出处理public void init() {}
}
解析配置得到List集合与遍历初始化Bean对象,具体代码详解如下:
import org.springframework.beans.factory.config.BeanDefinition;import java.util.ArrayList;
import java.util.List;/*** @author Kissship* @site www.Kissship.com* @company xxx公司* @create 2023-08-18-14:17*/
public class Demo1 {//初始化Beanpublic static void main(String[] args) throws ClassNotFoundException {
// 2.BeanDefinitionReader解析配置的JavaBean得到Beandefinition,最终得到List<BeanDefinition>集合List<BeanDefinition> beans = new ArrayList<>();//BeanDefinitionReader把spring-context.xml中所有的bean标签都解析成了List集合for (BeanDefinition bean : beans) {
// 4.Spring中的BeanFactory,会通过List<BeanDefinition>集合遍历初始化所有的JavaBean对象String beanClassName = bean.getBeanClassName();//得到的就是spring-context.xml中bean标签中class里的值Class.forName(beanClassName);//将配置的所有JavaBean进行反射实例化}}
}
如果自己的JavaBean需要调动Spring上下文中的资源(方法或属性),那么需要实现*Aware感知接口(比如BeanDefinition实现了BeanNameAware、ApplicationContextAware接口)具体详解如下:
Aware接口:
实现Aware接口:
1.2思考
那么现在有个问题,当我们的Spring容器初始化Bean完成之后,我们可能还需要加工一下,即进行再初始化。因为并不是每一个类都是我们自己写的。也许我们需要用别人的类内容,然后在此基础上再进行拓展。那么在此时我们能改动别人写的类里面的源码吗?不能。因为这样有可能影响到其他的功能,这时候我们的解决办法就是自己写一个类去继承别人的类然后进行再一波初始化,我们这里以BaseDao为例:
BaseDao为父类,MyBaseDao为子类:
我们需要在继承BaseDao方法后,在子类中进行初始化方法的重写(即再一次初始化),具体如下:
package com.kissship.beanlife;/*** @author Kissship* @site www.Kissship.com* @company xxx公司* @create 2023-08-18-15:58*/
//继承原本的BaseDao
public class MyBaseDao extends BaseDao{public MyBaseDao(){//重写初始化方法super();System.out.println("初始化...");}
}
那么在此时如果我们在初始化之后不满意,在初始化之后想修改Bean的内容,可以利用BeanPostProcessor后置处理器来完成。这时候可以在Bean对象实例化和引入注入完毕后,在显示调用初始化方法的前后添加自定义逻辑。(类似于AOP的环绕通知)环绕通知不了解的可以通过下面链接进行跳转至对应博客界面,如下:
Kissship的博客Spring之AOP篇https://blog.csdn.net/weixin_74263417/article/details/132340241?spm=1001.2014.3001.5501那么到这里我们就完成了Bean的创建工作。
2.Bean的单例与多例选择
1.在Spring中JavaBean默认是单例的,但是可以配置多例。
2.单例的优点:节约内存。弊端:有变量污染。
多例的优点:无变量污染。弊端:极其消耗内存。
3.单例:JavaBean是跟着spring上下文初始化的;容器生对象生,容器死对象死(此处对象指JavaBean)。
多例:JavaBean在使用时才会创建,销毁跟着jvm走。
4.第三点并不绝对正确,个别情况会有所个例。
2.1论证单例与多例优缺点
准备工作:
ParamAction:
package com.kissship.beanlife;import java.util.List;public class ParamAction {private int age;private String name;private List<String> hobby;private int num = 1;// private UserBiz userBiz = new UserBizImpl1();public ParamAction() {super();}public ParamAction(int age, String name, List<String> hobby) {super();this.age = age;this.name = name;this.hobby = hobby;}public void execute() {// userBiz.upload();// userBiz = new UserBizImpl2();System.out.println("this.num=" + this.num++);System.out.println(this.name);System.out.println(this.age);System.out.println(this.hobby);}
}
InstanceFactory(Bean工厂):
package com.kissship.beanlife;public class InstanceFactory {public void init() {System.out.println("初始化方法");}public void destroy() {System.out.println("销毁方法");}public void service() {System.out.println("业务方法");}
}
spring-context.xml进行配置(生命周期部分):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"default-autowire="byType"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"><!-- ioc的javabean-->
<!-- 凡是在Spring配置文件spring-context.xml中配置,那么该类javabean就交给了Spring容器管理--><bean class="com.kissship.ioc.web.UserAction" id="userAction"><property name="userService" ref="userService"></property>
<!-- <constructor-arg name="uname" value="扎克" ></constructor-arg>-->
<!-- <constructor-arg name="age" value="18" ></constructor-arg>-->
<!-- <constructor-arg name="hobby">-->
<!-- <list>-->
<!-- <value>唱,跳</value>-->
<!-- <value>Rap</value>-->
<!-- <value>篮球</value>-->
<!-- </list>-->
<!-- </constructor-arg>--></bean><bean class="com.kissship.ioc.web.GoodsAction" id="goodsAction"><property name="userService" ref="userServiceImpl1"></property>
<!-- <property name="gname" value="小文"></property>-->
<!-- <property name="age" value="19"></property>-->
<!-- <property name="peoples">-->
<!-- <list>-->
<!-- <value>印度飞饼</value>-->
<!-- <value>意大利炮</value>-->
<!-- <value>北京烤鸭</value>-->
<!-- <value>墨西哥卷</value>-->
<!-- </list>-->
<!-- </property>--></bean><bean class="com.kissship.ioc.service.impl.UserServiceImpl2" id="userService"></bean><bean class="com.kissship.ioc.service.impl.UserServiceImpl1" id="userServiceImpl1"></bean><!-- aop相关的Javabean--><!--目标对象--><bean class="com.kissship.aop.biz.impl.BookBizImpl" id="bookBiz"></bean><!--通知--><bean class="com.kissship.aop.advice.MyMethodBeforeAdvice" id="methodBeforeAdvice"></bean><bean class="com.kissship.aop.advice.MyAfterReturningAdvice" id="myAfterReturningAdvice"></bean><bean class="com.kissship.aop.advice.MyMethodInterceptor" id="myMethodInterceptor"></bean><bean class="com.kissship.aop.advice.MyThrowsAdvice" id="myThrowsAdvice"></bean><bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="regexpMethodPointcutAdvisor"><property name="advice" ref="myAfterReturningAdvice"></property><property name="pattern" value=".*buy"></property></bean><!--代理--><bean class="org.springframework.aop.framework.ProxyFactoryBean" id="bookProxy">
<!-- 配置目标对象--><property name="target" ref="bookBiz"></property>
<!-- 配置代理接口,目标对象的接口--><property name="proxyInterfaces"><list><value>com.kissship.aop.biz.IBookBiz</value></list></property>
<!-- 配置通知--><property name="interceptorNames"><list><value>methodBeforeAdvice</value>
<!-- <value>myAfterReturningAdvice</value>--><value>regexpMethodPointcutAdvisor</value><value>myMethodInterceptor</value><value>myThrowsAdvice</value></list></property></bean><!-- Spring的生命周期--><bean class="com.kissship.beanlife.ParamAction" id="paramAction"><constructor-arg name="name" value="刘三金"></constructor-arg><constructor-arg name="age" value="19"></constructor-arg><constructor-arg name="hobby"><list><value>来自星星的哥</value><value>天空一声巨响</value><value>劳资闪亮登场</value></list></constructor-arg></bean><bean class="com.kissship.beanlife.InstanceFactory" id="instanceFactory"scope="prototype" init-method="init" destroy-method="destroy"></bean></beans>
测试类Demo2:
package com.kissship.beanlife;import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;/** spring bean的生命週期* spring bean的單例多例*/
public class Demo2 {// 体现单例与多例的区别@Testpublic void test1() {ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
// ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");ParamAction p1 = (ParamAction) applicationContext.getBean("paramAction");ParamAction p2 = (ParamAction) applicationContext.getBean("paramAction");// System.out.println(p1==p2);p1.execute();p2.execute();// 单例时,容器销毁instanceFactory对象也销毁;多例时,容器销毁对象不一定销毁;applicationContext.close();}// 体现单例与多例的初始化的时间点 instanceFactory@Testpublic void test2() {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");}// BeanFactory会初始化bean对象,但会根据不同的实现子类采取不同的初始化方式// 默认情况下bean的初始化,单例模式立马会执行,但是此时XmlBeanFactory作为子类,单例模式下容器创建,bean依赖没有初始化,只有要获取使用bean对象才进行初始化@Testpublic void test3() {// ClassPathXmlApplicationContext applicationContext = new// ClassPathXmlApplicationContext("/spring-context.xml");Resource resource = new ClassPathResource("/spring-context.xml");BeanFactory beanFactory = new XmlBeanFactory(resource);
// InstanceFactory i1 = (InstanceFactory) beanFactory.getBean("instanceFactory");}}
执行Demo2结果如下:
那么我们换上多例后会是什么结果?
具体实操,在spring-context.xml中ParamAtion的Bean配置的class属性里加上scope属性并赋值多例(原型模式) ,如下:
修改后我们继续执行Demo2测试类看看效果:
2.2论证初始化时间点
Demo2里已经写了体现单例与多例的初始化时间点的方法,所以我们只需要在spring-context.xml中给它定一个多例的属性值然后测试看效果即可,xml代码如下:
<bean class="com.kissship.beanlife.InstanceFactory" id="instanceFactory"scope="prototype" init-method="init" destroy-method="destroy"></bean>
然后我们运行Demo2看看效果,如下:
紧接着我们换成单例,如下:
<bean class="com.kissship.beanlife.InstanceFactory" id="instanceFactory"scope="singleton" init-method="init" destroy-method="destroy"></bean>
执行方法看效果,如下:
那么现在问题又来了,虽然验证了单例与多例的初始化时间点,但是看不出到底是不是使用Spring创建的,那么现在我们上代码验证看看结果。刚刚我们在演示时多例并没有执行初始化方法,现在我们把xml文件里的单例改成多例,然后再Demo2测试类中加上以下代码:
然后再运行一次看效果:
2.3个例演示
BeanFactory会初始化bean对象,但会根据不同的实现子类采取不同的初始化方式。
默认情况下bean的初始化,单例模式会立马执行,但是此时XmlBeanFactory作为子类,单例模式下容器创建,bean依赖没有初始化·,只有要获取使用bean对象才进行初始化。
验证:
1.先把xml多例模式改为单例,然后运行Test2方法,再运行Test3方法,比较结果。
2.然后把Test3注释的代码部分放开再执行比较结果。
运行Test2的结果(先注释论证是否为Sprring创建新增的代码再运行):
运行Test3的结果:
然后取消注释,如下:
再执行一次Test3,效果如下:
最后Spring之bean的生命周期就到这里,祝大家在敲代码的路上一路通畅!
相关文章:

Spring之bean的生命周期
目录 1.Bean的初始化过程 1.1代码详解 1.2思考 2.Bean的单例与多例选择 2.1论证单例与多例优缺点 2.2论证初始化时间点 2.3个例演示 Spring Bean的生命周期: 一、通过XML、Java annotation(注解)以及Java Configuration(配置类),等方式…...

策略梯度方法
策略梯度方法 数学背景 给定一个标量函数 J ( θ ) J\left(\theta\right) J(θ),利用梯度上升法,使其最大化,此时的 π θ \pi_\theta πθ就是最优策略。 θ t 1 θ t α ∇ θ J ( θ t ) \theta_{t1}\theta_t\alpha \nabla_\theta…...

博客系统之单元测试
对博客系统进行单元测试 1、测试查找已存在的用户 测试名称 selectByUsernameTest01 测试源码 //查找用户,存在 Test public void selectByUsernameTest01 () { UserDao userDao new UserDao(); String ret1 userDao.selectByUsername("张三").toStr…...

【ARM v8】如何在ARM上实现x86的rdtsc()函数
博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持! 博主链接 本人就职于国际知名终端厂商,负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作,目前牵头6G算力网络技术标准研究。 博客…...

redis--事务
redis事务 在Redis中,事务是一组原子性操作的集合,它们被一起执行,要么全部执行成功,要么全部回滚。虽然Redis的事务并不遵循传统数据库的ACID特性,但它仍然提供了一种将多个命令打包成一组执行的机制,适用…...

111. 二叉树的最小深度
111. 二叉树的最小深度 给定一个二叉树,找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说明:叶子节点是指没有子节点的节点。 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeN…...

SpringMVC归纳与总结
前言 Spring的核心是IOC,一种依赖反转的解耦思想。MVC是一种处理Web请求的架构模式,当两者的作用结合,就形成了SpringMVC。 组成及运行原理 1. 两次映射 2. 为什么用适配器模式 过滤器与拦截器 1. 范围 静态资源与动态资源2. 生命周期…...

Python学习笔记_进阶篇(三)_django知识(二)
本章内容 Django model Model 基础配置 django默认支持sqlite,mysql, oracle,postgresql数据库。 <1> sqlite django默认使用sqlite的数据库,默认自带sqlite的数据库驱动 引擎名称:django.db.backends.sqlite3 <2>mysql …...

RISC-V 整型通用寄存器介绍
简介 RISC-V64位/32位提供了32个整型通用寄存器,编号是x0~x31,这些整型通用寄存器的宽度与架构位数一致。 浮点数寄存器与整形寄存器一样也提供了32个:f0~f31,位数与架构位数一致。 通用寄存器介绍 零寄存器 x0/zero x0寄存…...

学习Vue:【性能优化】异步组件和懒加载
在Vue.js应用开发中,性能优化是一个至关重要的主题,而异步组件和懒加载是提升性能的有效方法之一。本文将介绍什么是异步组件和懒加载,以及如何在Vue.js中应用这些技术来提升应用性能。 异步组件和懒加载 异步组件 异步组件是指在需要的时候…...

pdf格式文件下载不预览,云存储的跨域解决
需求背景 后端接口中返回的是pdf文件路径比如: pdf文件路径 (https://wangzhendongsky.oss-cn-beijing.aliyuncs.com/wzd-test.pdf) 前端适配是这样的 <ahref"https://wangzhendongsky.oss-cn-beijing.aliyuncs.com/wzd-test.pdf&…...

httplib + nlohmann::json上传数据时中文乱码解决
1、nlohmann::json 1.1 编码格式使用UTF-8 参考 nlohmann::json 中文乱码解决方案 (1)将数据先转为UTF-8格式 2、httplib 2.1 上传数据前 (1)调用httplib::Response对象的set_header()方法来设置编码格式 httplib::Response res…...

JavaScript中的设计模式之一--单例模式和模块
虽然有一种疯狂天才的感觉可能很诱人,但重新发明轮子通常不是设计软件的最佳方法。很有可能有人已经遇到了和你一样的问题,并以一种聪明的方式解决了它。这样的最佳实践在形式化后被称为设计模式。今天我们来看看它们的概念,并检查单例模式和…...

回归预测 | MATLAB实现GAM广义加性模型多输入单输出回归预测(多指标,多图)
回归预测 | MATLAB实现GAM广义加性模型多输入单输出回归预测(多指标,多图) 目录 回归预测 | MATLAB实现GAM广义加性模型多输入单输出回归预测(多指标,多图)效果一览基本介绍程序设计参考资料 效果一览 基本…...

css学习4(背景)
1、CSS中,颜色值通常以以下方式定义: 十六进制 - 如:"#ff0000"RGB - 如:"rgb(255,0,0)"颜色名称 - 如:"red" 2、background-image 属性描述了元素的背景图像. 默认情况下,背景图像进…...

二、SQL,如何实现表的创建和查询
1、新建表格(在当前数据库中新建一个表格): (1)基础语法: create table [表名]( [字段:列标签] [该列数据类型] comment [字段注释], [字段:列标签] [该列数据类型] comment [字段注释], ……,…...

大数据及软件教学与实验专业实训室建设方案
一 、系统概述 大数据及软件教学与实验大数据及软件教学与实验在现代教育中扮演重要角色,这方面的教学内容涵盖了大数据处理、数据分析、数据可视化和大数据应用等多个方面。以下是大数据及软件教学与实验的一般内容:1. 数据基础知识:教授学生…...

信创办公–基于WPS的EXCEL最佳实践系列 (公式和函数)
信创办公–基于WPS的EXCEL最佳实践系列 (公式和函数) 目录 应用背景相关知识操作步骤1、认识基本的初级函数2、相对引用,绝对引用,混合引用3、统计函数4、文本函数 应用背景 熟练掌握Excel的函数工具能让我们在日常的使用中更加方…...

【Apollo】自动驾驶感知——毫米波雷达
作者简介: 辭七七,目前大一,正在学习C/C,Java,Python等 作者主页: 七七的个人主页 文章收录专栏: 七七的闲谈 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖…...

SpringBoot部署到腾讯云
SpringBoot部署到腾讯云 此处默认已经申请到腾讯云服务器,因为本人还没有申请域名,所以就直接使用的ip地址 XShell连接到腾讯云 主机中填写腾讯云的公网ip地址 公网ip地址在下图中找到 接下来填写服务器的用户名与密码 一般centOS用户名为rootÿ…...

Git 设置代理
Git 传输分两种协议,SSH和 http(s),设置代理也需要分两种。 http(s) 代理 Command Line 使用 命令行 模式,可以在Powershell中使用以下命令设置代理: $env:http_proxy"http://127.0.0.1:7890" $env:https_proxy&quo…...

基于Spring Boot的机场VIP客户管理系统的设计与实现(Java+spring boot+MySQL)
获取源码或者论文请私信博主 演示视频: 基于Spring Boot的机场VIP客户管理系统的设计与实现(Javaspring bootMySQL) 使用技术: 前端:html css javascript jQuery ajax thymeleaf 微信小程序 后端:Java s…...

图数据库_Neo4j学习cypher语言_使用CQL_构建明星关系图谱_导入明星数据_导入明星关系数据_创建明星关系---Neo4j图数据库工作笔记0009
首先找到明星数据 可以看到有一个sheet1,是,记录了所有的关系的数据 然后比如我们搜索一个撒贝宁,可以看到撒贝宁的数据 然后这个是构建的CQL语句 首先我们先去启动服务 neo4j console 然后我们再来看一下以前导入的,可以看到导入很简单, 就是上面有CQL 看一下节点的属性...

恒运资本:算力概念强势拉升,亚康股份“20cm”涨停,首都在线等大涨
算力概念21日盘中强势拉升,到发稿,亚康股份“20cm”涨停,首都在线、汇金股份涨逾11%,鸿博股份亦涨停,南凌科技涨近9%,科创信息、神州数码、铜牛信息等涨超7%。 音讯面上,8月19日,202…...

Neo4j之union基础
UNION 用于将多个 MATCH 或 RETURN 子句的结果合并为一个结果集。它可以用来合并不同模式的节点和关系,或者将多个查询的结果合并在一起。以下是一些常用的示例和解释: 基本用法: MATCH (p:Person) WHERE p.age > 30 RETURN p.name AS n…...

搭建:基于nginx的上传功能
搭建:基于nginx的上传功能 文章目录 搭建:基于nginx的上传功能一、准备二、安装nginx1.1 解压nginx和nginx插件1.2 编译并安装nginx 三、启动一个python后台服务,用于上传到临时路径文件,转移到正式路径四、添加nginx配置…...

JavaScript高级
1、JavaScript面向对象 1.1、面向对象介绍 在 Java 中我们学习过面向对象,核心思想是万物皆对象。在 JavaScript 中同样也有面向对象。思想类似。 1.2、类的定义和使用 结构说明 代码实现 <!DOCTYPE html> <html lang"en"> <head>…...

隔断让你的办公室变得更加智能、环保、人性化
隔断可以在办公室中起到多种重要作用,使办公室更加智能、环保和人性化。以下是一些可能的方式: 1. 智能办公室控制系统:可以通过隔断集成智能办公室控制系统,实现办公室照明、温度和空调等设备的自动调节,提高能效和舒…...

web文件上传
文件上传指的是,将本地的图片、视频、音频上传到服务器,提供给其他用户浏览和下载的过程 前端需求 想要进行文件上传对于web前端来说有三个重要要素 1.<input type"file" name"image"> 提供这样的file文件上传格式 2. metho…...

二刷LeetCode--48. 旋转图像(C++版本),数学题
思路:主要是观察变化之后的数组和最开始的数组的区别,不难发现,先转置在左右镜像对称即可。需要注意的是转置和镜像对称中for变量的终止条件。 class Solution { public:void rotate(vector<vector<int>>& matrix) {// 行数…...