Spring5学习笔记 — IOC
✅作者简介:大家好,我是Cisyam,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉
🍎个人主页:Cisyam-Shark的博客
💞当前专栏: Spring专栏
✨特色专栏: MySQL学习
🥭本文内容:Spring5学习笔记 — IOC
🖥️个人小站 :个人博客,欢迎大家访问
📚个人知识库: 知识库,欢迎大家访问
1. 初始Spring
1.1 EJB存在的问题
EJB (Enterprise Java Beans) 是基于分布式事务处理的企业级应用程序的组件。Sun公司发布的文档中对EJB的定义是:EJB是用于开发和部署多层结构的、分布式的、面向对象的Java应用系统的跨平台的构件体系结构。
EJB是一个重量级框架 (opens new window):
- 运行环境苛刻
- 代码移植性差
1.2 什么是Spring
-
轻量级体现在哪里?
- 对运行环境没有额外要求
- 代码移植性高,不需要实现额外接口。
-
JavaEE解决方案:
-
Spring整合的设计模式:
1. 工厂模式 2. 代理模式 3. 模板模式 4. 策略模式
1.4 什么是设计模式
1.广义概念:面向对象设计中,解决特定问题的经典代码。
2.狭义概念:GOF4人帮定义的23种设计模式:工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式、设配器模式、桥接模式、过滤器模式、组合模式、装饰者模式、外观模式、享元模式、代理模式、责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、空对象模式、策略模式、模板模式、访问者模式
1.5 工厂设计模式
1.5.1 什么是工厂设计模式
1. 概念:创建对象交给工厂,而不是自己new
2. 优势:解耦合耦合:指代码间的强关联关系,一方的改变会影响另一方。问题:不利于代码的维护。User user = new User();
1.5.2 简单工厂的设计
package com.leo.basic;import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;public class BeanFactory {private static Properties env = new Properties();static{try {//第一步 获得IO输入流InputStream inputStream = BeanFactory.class.getResourceAsStream("applicationContext.properties");//第二步 文件内容 封装 Properties集合中 key = userService value = com.leo.UserServiceImplenv.load(inputStream);} catch (IOException e) {e.printStackTrace();}}/*对象的创建方式:1. 直接调用构造方法 创建对象 UserService userService = new UserServiceImpl();2. 通过反射的形式 创建对象 解耦合Class clazz = Class.forName("com.leo.basic.UserServiceImpl");UserService userService = (UserService)clazz.newInstance();*/public static UserService getUserService(){UserService userService = null;try {// com.leo.basic.UserServiceImplClass clazz = Class.forName(env.getProperty("userService"));userService = (UserService) clazz.newInstance();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}return userService;}public static UserDao getUserDao(){UserDao userDao = null;try {Class clazz = Class.forName(env.getProperty("userDao"));userDao = (UserDao) clazz.newInstance();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}return userDao;}
}
1.5.3 通用的工厂设计
代码
package com.leo.basic;import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;public class BeanFactory {private static Properties env = new Properties();static{try {//第一步 获得IO输入流InputStream inputStream = BeanFactory.class.getResourceAsStream("applicationContext.properties");//第二步 文件内容 封装 Properties集合中 key = userService value = com.leo.UserServiceImplenv.load(inputStream);} catch (IOException e) {e.printStackTrace();}}//通用工厂public static Object getBean(String key){Object res = null;try {Class clazz = Class.forName(env.getProperty(key));res = clazz.newInstance();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}return res;}
}
- 通用工厂的使用方式:
1. 定义类型 (类)
2. 通过配置文件的配置告知工厂(applicationContext.properties)key = value
3. 通过工厂获得类的对象Object ret = BeanFactory.getBean("key")
1.5.4 总结
**Spring本质:**工厂 ApplicationContext (applicationContext.xml)
1.6 Spring 框架概念
Spring 是众多开源java项目中的一员,基于分层的javaEE应用一站式轻量级开源框架,主要核心是 IOC(控制反转/依赖注入)与 AOP(面向切面)两大技术,实现项目在开发过程中的轻松解耦,提高项目的开发效率。
在项目中引入 Spring 立即可以带来下面的好处 降低组件之间的耦合度,实现软件各层之间的解耦。可以使用容器提供的众多服务,如:事务管理服务、消息服务等等。当我们使用容器管理事务时,开发人员就不再需要手工控制事务.也不需处理复杂的事务传播。 容器提供单例模式支持,开发人员不再需要自己编写实现代码。 容器提供了AOP技术,利用它很容易实现如权限拦截、运行期监控等功能。
1.7 Spring 源码架构
Spring 总共大约有20个模块,由1300多个不同的文件构成。而这些组件被分别整合在核心容器(Core Container)、Aop(Aspect Oriented Programming)和设备支持(Instrmentation)、数据访问及集成(Data Access/Integeration)、Web、报文发送(Messaging)、测试6个模块集合中。
-
核心容器
:Spring-beans 和 Spring-core 模块是 Spring 框架的核心模块,包含控制反转(Inversion of Control, IoC)和依赖注入(Dependency Injection, DI),核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,工厂模式的实现。BeanFactory 使用控制反转(IOC) 思想将应用程序的配置和依赖性规范与实际的应用程序代码分开。Spring 上下文Spring Context:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
Spring-Expression 模块是统一表达式语言(unified EL)的扩展模块,可以查询、管理运行中的对象,同时也方便的可以调用对象方法、操作数组、集合等。它的语法类似于传统EL,但提供了额外的功能,最出色的要数函数调用和简单字符串的模板函数。
-
Spring-AOP
:Spring-aop是Spring的另一个核心模块, 在Spring中,他是以JVM的动态代理技术为基础,然后设计出了一系列的Aop横切实现,比如前置通知、返回通知、异常通知等。通过其配置管理特性,Spring AOP 模块直接将面向切面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。 -
Spring Data Access(数据访问)
:由Spring-jdbc、Spring-tx、Spring-orm、Spring-jms和Spring-oxm 5个模块组成 Spring-jdbc 模块是 Spring 提供的JDBC抽象框架的主要实现模块,用于简化 Spring JDBC。Spring-tx 模块是SpringJDBC事务控制实现模块。使用Spring框架,它对事务做了很好的封装,通过它的Aop配置,可以灵活的配置在任何一层。
Spring-Orm 模块是ORM框架支持模块,主要集成 hibernate, Java Persistence API (JPA) 和 Java Data Objects (JDO) 用于资源管理、数据访问对象(DAO)的实现和事务策略。
Spring-Jms 模块(Java Messaging Service)能够发送和接受信息。
Spring-Oxm 模块主要提供一个抽象层以支撑OXM(OXM 是 Object-to-XML-Mapping 的缩写,它是一个O/M-mapper,将java对象映射成 XML 数据,或者将 XML 数据映射成 java 对象),例如:JAXB, Castor, XMLBeans, JiBX 和 XStream 等。
-
Web 模块
:由Spring-web、Spring-webmvc、Spring-websocket和Spring-webmvc-portlet 4个模块组成,Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。 -
报文发送
:即Spring-messaging模块。Spring-messaging是Spring4 新加入的一个模块,主要职责是为Spring 框架集成一些基础的报文传送应用。
-
单元测试
:即Spring-test模块。Spring-test模块主要为测试提供支持
1.8 第一个Spring程序
1. 软件版本
1. JDK1.8+
2. Maven3.5+
3. IDEA2018+
4. SpringFramework 5.1.4 官方网站 www.spring.io
2. 环境搭建
- Spring的jar包(在pom.xml中加入依赖)
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.4.RELEASE</version>
</dependency>
- Spring的配置文件
1. 配置文件的放置位置:任意位置,没有硬性要求
2. 配置文件的命名:没有硬性要求,但建议:applicationContext.xml思考:日后应用Spring框架时,需要进行配置文件路径的设置。
3. Spring的核心API
ApplicationContext
作用:Spring提供的ApplicationContext这个工厂,用于对象的创建
好处:解耦合
- 特点:
ApplicationContext是接口类型,屏蔽了实现的差异。
非web环境 : ClassPathXmlApplicationContext (main junit)
web环境 : XmlWebApplicationContext
- 重量级资源
ApplicationContext工厂的对象占用大量内存。
不会频繁的创建对象 : 一个应用只会创建一个工厂对象。
ApplicationContext工厂:一定是线程安全的(多线程并发访问)
4. 程序开发
- 创建类型
- 配置文件的配置 applicationContext.xml
- 通过工厂类,获得对象
ApplicationContext
|- ClassPathXmlApplicationContext
ApplicationContext ctx = new ClassPathXmlApplicationContext(“/applicationContext.xml”);
Person person = (Person)ctx.getBean(“person”);
5. 细节分析
- 名词解释
Spring工厂创建的对象,叫做bean或者组件(component)
- Spring工厂相关的方法
//这种方式获取对象,不需要强制类型转换
Person person = ctx.getBean("person", Person.class);
System.out.println("person = " + person);//当前Spring的配置文件中 只能有一个<bean class是Person类型
Person person1 = ctx.getBean(Person.class);
System.out.println("person1 = " + person1);//获取配置文件中所有bean标签的id值 person person1
String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println("beanDefinitionName = " + beanDefinitionName);
}//根据类型获取配置文件中对应bean标签的id值
String[] beanNamesForType = ctx.getBeanNamesForType(Person.class);
for (String id : beanNamesForType) {
System.out.println("id = " + id);
}//用于判断是否存在指定id值的bean,不能判断name值
System.out.println(ctx.containsBeanDefinition("a"));//用于判断是否存在指定id值的bean,可以判断name值
System.out.println(ctx.containsBean("person"));
-
配置文件中需要注意的细节
只配置class属性
<bean class="com.leo.demo01.pojo.Person"/>
- 上述这种配置,没有指定id,Spring会自动生成一个 id,
com.leo.demo01.pojo.Person#0
,可以使用getBeanNamesForType()
等方法验证。 - 应用场景:
如果这个bean只需要使用一次,那么就可以省略id值 如果这个bean会使用多次,或者被其他bean引用则需要设置id值
name属性
- 作用:用于在Spring的配置文件中,为bean对象定义别名(小名)
- name与id的相同点:
ctx.getBean("id")
或ctx.getBean("name")
都可以创建对象;<bean id="person" class="Person"/>
与<bean name="person" class="Person"/>
等效;
name
与id
的不同点:- 别名可以定义多个,但是 id 属性只能有⼀个值;
- XML 的 id 属性的值,命名要求:必须以字⺟开头,可以包含 字⺟、数字、下划线、连字符;不能以特殊字符开头
/person
; - XML 的 name 属性的值,命名没有要求,
/person
可以。 但其实 XML 发展到了今天:ID属性的限制已经不存在,/person
也可以。
6. Spring工厂的底层实现原理(简易版)
2. Spring5与日志框架的整合
2.1 为什么要整合日志框架?
Spring与日志框架进行整合,日志框架就可以在控制台中,输出Spring框架运行过程中的一些重要的信息。 好处:便于了解Spring框架的运行过程,利于程序的调试
默认日志框架 Spring 1.x、2.x、3.x 早期都是基于
commonslogging.jar
Spring 5.x 默认整合的⽇志框架 logback、log4j2
2.2 Spring如何整合日志框架?
以Spring5整合log4j
为例
pom.xml
文件添加log4j
依赖:相当于导入了log4j.jar包
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.25</version>
</dependency>
<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version>
</dependency>
- 引⼊
log4.properties
配置⽂件:
# resources文件夹根目录下
### 配置根
log4j.rootLogger = debug,console### 日志输出到控制台显示
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
3. Spring IOC 容器 Bean 对象实例化
思路:
-
定义Bean 工厂接口,提供获取bean方法
-
定义Bean工厂接口实现类,解析配置文件,实例化Bean对象
-
实现获取Bean方法
3.1 定义 Bean 属性对象
package com.leo.demo01.pojo;/*** bean对象* 用来接收配置文件中bean标签的id与class属性值* @author gaoziman*/
public class MyBean {// bean对象的id属性值private String id; // bean对象的类路径private String clazz; public MyBean() {}public MyBean(String id, String clazz) {this.id = id;this.clazz = clazz;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getClazz() {return clazz;}public void setClazz(String clazz) {this.clazz = clazz;}
}
3.2 添加 dom4j 坐标依赖
<!-- dom4j -->
<dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version>
</dependency>
<!-- XPath -->
<dependency><groupId>jaxen</groupId><artifactId>jaxen</artifactId><version>1.1.6</version>
</dependency>
3.3 准备自定义配置文件
<?xml version="1.0" encoding="utf-8" ?>
<beans><bean id="userService" class="com.leo.service.UserService"></bean><bean id="accountService" class="com.leo.service.AccountService"></bean>
</beans>
3.4 定义 Bean 工厂接口
package com.leo.spring;/*** Bean 工厂接口定义*/
public interface MyFactory {// 通过id值获取对象public Object getBean(String id);
}
3.5 定义 Bean 接口的实现类
package com.leo.spring;import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** 模拟Spring的实现* 1、通过构造器得到相关配置文件* 2、通过dom4j解析xml文件,得到List 存放id和class* 3、通过反射实例化得到对象 Class.forName(类的全路径).newInstance(); 通过Map<id,Class>存储* 4、得到指定的实例化对象*/
public class MyClassPathXmlApplicationContext implements BeanFactory {private Map beans = new HashMap(); // 实例化后的对象放入mapprivate List<MyBean> myBeans; // 存放已读取bean 配置信息/* 1、通过构造器得到相关配置文件 */public MyClassPathXmlApplicationContext(String fileName) {/* 2、通过dom4j解析xml文件,得到List (存放id和class) */this.parseXml(fileName);/* 3、通过反射实例化得到对象Class.forName(类路径).newInstance(); 通过Map存储 */this.instanceBean();}/*** 通过dom4j解析xml文件,得到List 存放id和class* 1、获取解析器* 2、得到配置文件的URL* 3、通过解析器解析xml文件(spring.xml)* 4、通过xpath语法,获取beans标签下的所有bean标签* 5、通过指定语法解析文档对象,返回集合* 6、判断集合是否为空,遍历集合* 7、获取标签元素中的属性* 8、得到Bean对象,将Bean对象设置到集合中* @param fileName*/private void parseXml(String fileName) {// 1、获取解析器SAXReader reader = new SAXReader();// 2、得到配置文件的URLURL url = this.getClass().getClassLoader().getResource(fileName);try {// 3、通过解析器解析xml文件(spring.xml)Document document = reader.read(url);// 4、通过xpath语法,获取beans标签下的所有bean标签XPath xPath = document.createXPath("beans/bean");// 通过指定语法解析文档对象,返回集合List<Element> list = xPath.selectNodes(document);// 判断集合是否为空,遍历集合if (list != null && list.size() > 0) {myBeans = new ArrayList<>();for(Element el : list) {// 获取标签元素中的属性String id = el.attributeValue("id"); // id 属性值String clazz = el.attributeValue("class"); // class 属性值System.out.println(el.attributeValue("id"));System.out.println(el.attributeValue("class"));// 得到Bean对象MyBean bean = new MyBean(id, clazz);// 将Bean对象设置到集合中myBeans.add(bean);}}} catch (DocumentException e) {e.printStackTrace();}}/*** 通过反射实例化得到对象 * Class.forName(类的全路径).newInstance(); * 通过Map<id,Class>存储*/private void instanceBean() {// 判断bean集合是否为空,不为空遍历得到对应Bean对象if (myBeans != null && myBeans.size() > 0) {for (MyBean bean : myBeans){ try {// 通过类的全路径实例化对象Object object = Class.forName(bean.getClazz()).newInstance();// 将id与实例化对象设置到map对象中beans.put(bean.getId(), object);} catch (Exception e) {e.printStackTrace();}}}}/*** 通过key获取map中的指定value* @param id* @return*/@Overridepublic Object getBean(String id) {Object object = beans.get(id);return object;}
}
3.6 测试自定义 IOC 容器
-
创建与配置文件中对应的Bean对象
UserService.java
package com.leo.service;public class UserService {public void test(){System.out.println("UserService Test...");} }
AccountService.java
package com.leo.service;public class AccountService {public void test(){System.out.println("AccountService Test...");} }
-
测试是否可以获取实例化的Bean对象
package com.leo;import com.leo.spring.MyFactory; import com.leo.spring.MyClassPathXmlApplicationContext; import com.leo.service.AccountService; import com.leo.service.UserService;public class App {public static void main(String[] args) {MyFactory factory = new MyClassPathXmlApplicationContext("spring.xml");// 得到实例化对象UserService userService = (UserService) factory.getBean("userService");userService.test();UserService userService2 = (UserService) factory.getBean("userService");System.out.println(userService+"=====" + userService2);AccountService accountService = (AccountService)factory.getBean("accountService");accountService.test();} }
4. Spring IOC 配置文件加载
4.1 Spring 配置文件加载
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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="userService" class="com.xxxx.service.UserService"></bean>
</beans>
4.2 根据相对路径加载资源
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
4.3 根据绝对路径加载资源
ApplicationContext ac = new FileSystemXmlApplicationContext("E:\code-myself\spring-demo\spring-demo01\src\main\resources\spring.xml");
5. 注入
5.1 什么是注入
通过Spring工厂及配置文件,为所创建对象的成员变量赋值
5.2 为什么要注入
- 通过编码的方式,为成员变量进行赋值,存在耦合
- 注入的好处: 解耦合
public void test03(){ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");Person person = (Person) ctx.getBean("person");//通过代码为变量赋值, 存在耦合, 如果以后想修改变量的值, 需要修改代码, 重新编译person.setName("Leo");person.setAge(16);System.out.println("person = " + person);
}
5.3 如何注入
- 前提:类的成员变量提供set get方法
- 配置Spring配置文件
<bean name="person" class="com.leo.demo01.pojo.Person" ><property name="name" value="Leo" /><property name="age" value="20" />
</bean>
5.4 Spring注入的原理分析
Spring通过底层调用对象属性对应的set方法,完成成员变量的赋值,这种方式我们也称之为set注入
6. Set注入详解
针对于不同类型的成员变量,需要在<property>
标签中嵌套其他标签:
<property>xxxxx
</property>】
6.1 JDK内置类型
1. String+8中基本类型
<bean name="person" class="com.leo.demo01.pojo.Person" ><property name="name" value="Leo" /><property name="age" value="20" />
</bean>
2. 数组
<!-- list标签 -->
<property name="emails"><list><value>1234@qq.com</value><value>yangGuo@qq.com</value><value>baiXiaoSheng@qq.com</value><value>Trump@qq.com</value></list>
</property>
3. Set集合
<!-- set标签 -->
<property name="tels"><set><value>131********</value><value>159********</value><value>176********</value></set>
</property>
<!-- Set集合中有非基本类型时: -->
<set><ref bean<set
</set>
4. List集合
<!-- list标签 -->
<property name="address"><list><value>花果山水帘洞</value><value>铁岭</value><value>东土大唐</value></list>
</property>
<!-- List集合中有非基本类型时: -->
<list><ref bean<set
</list>
5. Map集合
<!-- 需要用到map entry key三个标签 -->
<property name="qqs"><map><entry><key><value>周芷若</value></key><value>备胎</value></entry><entry><key><value>赵敏</value></key><value>爱人</value></entry></map>
</property>
<!-- Map集合中有非基本类型时: -->
<entry><key><value>chenyn</value></key><ref bean
</entry>
6. Properties
<!-- props和prop标签 -->
<property name="p"><props><prop key="唐僧">白骨精</prop><prop key="Tom">Jerry</prop></props>
</property>
7. 复杂的JDK类型(比如Date)
需要自定义类型转换器处理
6.2 用户自定义类型
1 方式一
- 为成员变量提供get set方法
- 配置文件中赋值(注入)
2 方式二
方式一存在的问题:
- 配置文件代码冗余。
- 被注入的对象(UserDAO),多次创建,浪费(JVM)内存资源。
- 为成员变量提供set get方法
- 配置文件中进行配置
注意: Spring4.x 废除了 <ref local=""/>
基本等效 <ref bean=""/>
;
3. 基于p命名空间的简化
-
JDK类型:
<!-- 简化前:--> <bean id="person3" class="com.leo.basic.Person"><property name="name"><value>沙和尚</value></property> </bean><!-- 简化后:--> <bean id="person3" class="com.leo.basic.Person" p:name="沙和尚"/>
-
用户自定义类型:
<!-- 简化前:--> <bean id="userDao" class="com.leo.basic.UserDaoImpl"/> <bean id="userService" class="com.leo.basic.UserServiceImpl"><property name="userDao"><ref bean="userDao"/></property> </bean><!-- 简化后:--> <bean id="userService1" class="com.leo.basic.UserServiceImpl" p:userDao-ref="userDao"/>
7. 构造器注入
构造注入:Spring解析配置文件,调用构造方法,为成员变量赋值。
7.1 开发步骤
-
提供带参数构造方法
public class Customer implements Serializable {private String name;private int age;//带参构造方法:public Customer(String name, int age) {this.name = name;this.age = age;} }
-
Spring配置文件中赋值(
注入
)<bean id="customer" class="com.leo.basic.constructor.Customer"><constructor-arg><value>武松</value></constructor-arg><constructor-arg><value>6666</value></constructor-arg> </bean>
7.2 构造方法重载
参数个数不同时
通过控制<constructor-arg>标签的数量进行区分
参数个数相同时
通过在标签引入 type属性 进行类型的区分 <constructor-arg type="">
7.3 注入总结
实战中,应用set注入还是构造注入?
答案:set注入更多,原因如下:
- 构造注入麻烦 (重载)。
- Spring框架底层大量应用了 set注入
持续更新中…
相关文章:

Spring5学习笔记 — IOC
✅作者简介:大家好,我是Cisyam,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Cisyam-Shark的博客 💞当前专栏: Spring专栏 ✨特色专栏&a…...

DevOps自动化平台开发之 Shell脚本执行的封装
基础知识 基于如下技术栈开发DevOps平台 Spring Boot Shell Ansible Git Gitlab Docker K8S Vue 1、spring boot starter的封装使用 2、Shell脚本的编写 3、Ansible 脚本的编写 4、Docker 的使用与封装设计 本篇介绍如何使用Java封装Linux命令和Shell脚本的使用 将其设计成…...

STM32CubeIDE(I2C)
目录 一、IIC轮询模式 1.1 配置 1.2 编写AHT20驱动 1.2.1 aht20.h 1.2.2 aht20.c 二、I2C中断 2.1 打开中断 2.2 分离读取流程 2.3 在主函数中重新编写读取流程 2.4 在i2c.c中重新定义stm32f1xx_hal_i2c.h中的两个函数 三、I2CDMA 3.1 配置DMA通道 3.2 代码的修改 一…...

http 请求报文响应报文的格式以及Token cookie session 区别
面试必备 http 请求报文响应报文的格式Token cookie session 区别 http 请求报文响应报文的格式 HTTP 请求报文和响应报文的格式如下: HTTP 请求报文格式: <方法> <路径> <协议版本> <请求头部字段1>: <值1> <请求头…...

智能汽车的主动悬架工作原理详述
摘要: 本文将详细介绍主动悬架功能原理设计。 主动悬架是车辆上的一种汽车悬架。它使用车载系统来控制车轮相对于底盘或车身的垂直运动,而不是由大弹簧提供的被动悬架,后者的运动完全由路面决定。主动悬架分为两类:真正的主动悬架…...

vue2和vue3的一些技术点复习
二、vue2 1、vue2对已有组件二次封装,例如fes2 input 组件(文档链接) 子组件 <template><div class"keyboard-page"><wb-input:id"keyBoardId":placeholder"placeholder" :type"type&q…...

安装nvm 切换node版本
1. 安装 nvm curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.1/install.sh | bash 验证nvm安装完成 command -v nvm 如果安装完成,就会显示如下 nvm 2. 查看 nvm 可以安装的 node 版本 查看可以安装的版本 nvm ls-remote 查看所有可以安装的…...

【html中的BFC是什么】
BFC(块级格式化上下文)是 CSS 中的一种盒模型布局,是指一个独立的块级容器,容器内部的元素会按照一定规则进行布局。 BFC 具体的规则有以下几个: BFC 内部的元素在垂直方向上相互排列,不会出现浮动的情况。…...

苹果账号被禁用怎么办
转载:苹果账号被禁用怎么办 目录 禁用的原因 解除Apple ID禁用 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UKQ1ILhC-1689932607373)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw)]编辑 …...

跨境出海企业,如何防范恶意退货欺诈
很多出海企业遭遇到过恶意退货事件。 2021年,某跨境商家在海外电商平台运营超过13年。有一次,有个海外买家买了一台二手的数码摄像机。在买家收到货后,却声称商品备在使用了45分钟之后便自动关机,且不能继续充电。该商家很肯定产…...

数据出境要依法“过安检”!什么是数据出境?
为了规范数据出境活动,保护个人信息权益,维护国家安全和社会公共利益,促进数据跨境安全、自由流动。从2022年9月1日起,《数据出境安全评估办法》施行。什么是数据出境,什么情况下需要进行数据出境安全评估呢࿱…...

ARM——点灯实验
循环点灯 RCC寄存器使能GPIOE、GPIOF组寄存器 修改GPIOx组寄存器下的值 通过GPIOx_MODER寄存器设置为输出模式通过GPIOx_OTYOER寄存器设置为推挽输出类型通过GPIOx_OSPEEDR寄存器设置为低速输出通过GPIOx_PUPDR寄存器设置为禁止上下拉电阻点灯 通过GPIOx_ODR寄存器设置为高电…...

Kubernetes 使用 helm 部署 NFS Provisioner
文章目录 1. 介绍2. 预备条件3. 部署 nfs4. 部署 NFS subdir external provisioner4.1 集群配置 containerd 代理4.2 配置代理堡垒机通过 kubeconfig 部署 部署 MinIO添加仓库修改可配置项 访问nodepotingress 1. 介绍 NFS subdir external provisioner 使用现有且已配置的NFS…...

Istio Pilot源码学习(二):ServiceController服务发现
本文基于Istio 1.18.0版本进行源码学习 4、服务发现:ServiceController ServiceController是服务发现的核心模块,主要功能是监听底层平台的服务注册中心,将平台服务模型转换成Istio服务模型并缓存;同时根据服务的变化,…...

Spring框架中的ResourcePatternResolver只能指定jar包内文件,指定容器中文件路径报错:FileNotFoundException
原始代码: public static <T> T getFromFile(String specifiedFile, String defaultClasspathFile, Class<T> expectedClass) {try {ResourcePatternResolver resolver new PathMatchingResourcePatternResolver();Resource[] resources resolver.ge…...

pytorch工具——认识pytorch
目录 pytorch的基本元素操作创建一个没有初始化的矩阵创建一个有初始化的矩阵创建一个全0矩阵并可指定数据元素类型为long直接通过数据创建张量通过已有的一个张量创建相同尺寸的新张量利用randn_like方法得到相同尺寸张量,并且采用随机初始化的方法为其赋值采用.si…...

解决Jmeter响应内容显示乱码
一、问题描述 jmeter在执行接口请求后,返回的响应体里面出现乱码现象,尽管在调了对应请求的响应编码也无用,现找到解决办法。 二、解决办法 进入到jmeter的bin目录下,找到jmeter.properties,通过按ctrlF快速定位查找到…...

ChatGPT和搜索引擎哪个更好用
目录 ChatGPT和搜索引擎的概念 ChatGPT和搜索引擎的作用 ChatGPT的作用 搜索引擎的作用 ChatGPT和搜索引擎哪个更好用 总结 ChatGPT和搜索引擎的概念 ChatGPT是一种基于对话的人工智能技术,而搜索引擎则是一种用于在互联网上查找和检索信息的工具。它们各自具…...

Nginx 301 https跳转后出现跨域和混合内容问题 —— 筑梦之路
问题 在浏览器地址栏敲入url访问静态资源目录时,发现默认跳转到了http协议的地址 如上图所示,客户端https请求先到达API网关,然后网关将请求通过http协议转发到静态资源服务器。 调出浏览器发现客户端发送的https请求收到了一个301状态码的响…...

记录--关于前端的音频可视化-Web Audio
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 背景 最近听音乐的时候,看到各种动效,突然好奇这些音频数据是如何获取并展示出来的,于是花了几天功夫去研究相关的内容,这里只是给大家一些代码实例&…...

docker-compose yml配置、常用命令
下载完docker-compose后,如果想使用docker-compose命令开头,需要创建软连接 sudo ln -s /usr/local/lib/docker/cli-plugins/docker-compose /usr/bin/docker-compose 1.docker-compose.yml文件编排 一个 docker-compose.yml 文件的顶层元素有ÿ…...

【实战】 七、Hook,路由,与 URL 状态管理(下) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(十三)
文章目录 一、项目起航:项目初始化与配置二、React 与 Hook 应用:实现项目列表三、TS 应用:JS神助攻 - 强类型四、JWT、用户认证与异步请求五、CSS 其实很简单 - 用 CSS-in-JS 添加样式六、用户体验优化 - 加载中和错误状态处理七、Hook&…...

【MySQL】_5.MySQL的联合查询
目录 1. 笛卡尔积 2. 内连接 2.1 示例1:查询许仙同学的成绩 2.2 示例2: 查询所有同学的总成绩,及同学的个人信息 2.3 示例3:查询所有同学的科目及各科成绩,及同学的个人信息 3. 外连接 3.1 情况一:两…...

【后端面经】微服务构架 (1-3) | 熔断:熔断-恢复-熔断-恢复,抖来抖去怎么办?
文章目录 一、前置知识1、什么是熔断?2、什么是限流?3、什么是降级?4、怎么判断微服务出现了问题?A、指标有哪些?B、阈值如何选择?C、超过阈值之后,要不要持续一段时间才触发熔断?5、服务恢复正常二、面试环节1、面试准备2、面试基本思路三、总结 在微服务构架中…...

对UITextField输入内容的各种限制-总结
使用代理方法来限制输入框中的字数,输入的符号,输入的数字大小等各种限制 限制输入字数 已经有小数点了,就不能继续输入小数点 不能输入以0为开头的内容 不能输入以.为开头的内容 小数点后只允许输入一位数 只能输入100以下的数值 **不能包括…...

【图论】二分图
二分图,即可以将图中的所有顶点分层两个点集,每个点集内部没有边 判定图为二分图的充要条件:有向连通图不含奇数环 1、染色法 可以解决二分图判断的问题 步骤与基本思路 遍历图中每一个点,若该点未被染色,则遍历该…...

数据结构——(一)绪论
👉数据元素整体思维导图 欢迎补充 一、基本概念❤️ 1.1基本术语⭐️ (1)数据 客观事务属性的数字、字符。 (2)数据元素 数据元素是数据的基本单位,一个数据元素可由若干数据项组成,数据项是…...

[ 华为云 ] 云计算中Region、VPC、AZ 是什么,他们又是什么关系,应该如何抉择
前几天看到一个问答帖,我回答完了才发现这个帖子居然是去年的也没人回复,其中他问了一些华为云的问题,对于其中的一些概念,这里来总结讲解一下,希望对学习华为云的小伙伴有所帮助。 文章目录 区域(Region&a…...

表单验证:输入的字符串以回车分隔并验证是否有
公司项目开发时,有一个需求,需要对输入的字符串按回车分隔并验证是否有重复项,效果如下: 表单代码: <el-form-item label"IP地址条目:" prop"ipAddressEntry"><el-inputtype&…...

智能财务分析-亿发财务报表管理系统,赋能中小企业财务数字化转型
对于许多中小企业来说,企业重要部门往往是财务和业务部门。业务负责创收,财务负责控制成本,降低税收风险。但因管理机制和公司运行制度的原因,中小企业往往面临着业务与财务割裂的问题,财务数据不清晰,无法…...