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

Spring IoC 深度学习

Io回顾 

IoC 是 Inversion of Control 的简写,译为“控制反转”,它不是一门技术,而是一种设计思想,是一个重要的面向对象编程法则,能够指导我们如何设计出松耦合、更优良的程序。

Spring 通过 IoC 容器来管理所有 Java 对象的实例化和初始化,控制对象与对象之间的依赖关系。我们将由 IoC 容器管理的 Java 对象称为 Spring Bean,它与使用关键字 new 创建的 Java 对象没有任何区别。

IoC 容器是 Spring 框架中最重要的核心组件之一,它贯穿了 Spring 从诞生到成长的整个过程。

基础知识可以参考:

IoC基础

IoC引用外部属性文件

引入context的名称空间:

<?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"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.xsd"></beans>

引入jdbc的依赖:

 <!-- MySQL驱动 -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version>
</dependency><!-- 数据源 -->
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.15</version>
</dependency>

在resources中创建jdbc的配置文件。(写一些测试数据)

jdbc.user=root
jdbc.password=atguigu
jdbc.url=jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
jdbc.driver=com.mysql.cj.jdbc.Driver

创建bean-jdbc.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:context="http://www.springframework.org/schema/context"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.xsd">
<!--    引入外部的数据源配置文件--><context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<!--    通过数据源的文件将数据注入bean中-->
<!--    通过${}在数据源的配置文件中进行取值--><bean id="jdbcDriver" class="com.alibaba.druid.pool.DruidDataSource"><property name="url" value="${jdbc.url}"></property><property name="username" value="${jdbc.user}"></property><property name="password" value="${jdbc.password}"></property><property name="driverClassName" value="${jdbc.driver}"></property></bean>
</beans>

 创建测试类进行测试。

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;@Testvoid test7() throws SQLException {ApplicationContext context = new ClassPathXmlApplicationContext("bean-jdbc.xml");DataSource bean = context.getBean(DataSource.class);Connection connection = bean.getConnection();System.out.println(connection);}

测试结果:

bean的作用域

 单例&多例

在bean中使用scope属性设置单例和多例,使用singleton/prototype。(默认使用单例)

 生命周期

  • bean对象创建(调用无参构造器)

  • 给bean对象设置属性

  • bean的后置处理器(初始化之前)

  • bean对象初始化(需在配置bean时指定初始化方法)

  • bean的后置处理器(初始化之后)

  • bean对象就绪可以使用

  • bean对象销毁(需在配置bean时指定销毁方法)

  • IOC容器关闭  

进行测试 :

创建一个life类

public class Life {String name;//创建无参构造public Life() {System.out.println("1.创建一个空的实体类");}//初始化方法public void initMethod() {System.out.println("4.使用了初始化函数");}//销毁方法public void destroyMethod() {System.out.println("7.使用了摧毁函数");}public String getName() {return name;}public void setName(String name) {System.out.println("2.给属性进行赋值");this.name = name;}}

创建Spring的配置文件bean-life.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"><bean id="life" class="com.huang.Life" init-method="initMethod" destroy-method="destroyMethod" scope="singleton"><property name="name" value="hfw"></property></bean>
</beans>

编写测试代码

    @Testvoid test1() {//ApplicationContext接口没有close方法,要使用ClassPathXmlApplicationContext实现类进行CLose操作ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean-life.xml");Life life = (Life) context.getBean("life");System.out.println("6.获取到了完整的实体类");context.close();}

测试结果

 编写后置处理器

bean的后置处理器会在生命周期的初始化前后添加额外的操作,需要实现BeanPostProcessor接口,且配置到IOC容器中,需要注意的是,bean后置处理器不是单独针对某一个bean生效,而是针对IOC容器中所有bean都会执行。(默认使用BeanPostProcessor)

在BeanPostProcessor接口中存在俩个方法,就是对应初始化前后的方法。

所以我们创建自己的后置处理器时就是去实现这两个方法。

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;public class MyBeanProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("3.在初始化之前的后置处理器");return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("5.在初始化之后的后置处理器");return bean;}
}

将MyBeanprocessor在bean-life.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"><bean id="life" class="com.huang.Life" init-method="initMethod" destroy-method="destroyMethod" scope="singleton"><property name="name" value="hfw"></property></bean><bean id="myBeanProcessor" class="com.huang.MyBeanProcessor"></bean>
</beans>

进行测试,结果为下

FactoryBean(不是BeanFactory)

 FactoryBean是Spring提供的一种整合第三方框架的常用机制。和普通的bean不同,配置一个FactoryBean类型的bean,在获取bean的时候得到的并不是class属性中配置的这个类的对象,而是getObject()方法的返回值。通过这种机制,Spring可以帮我们把复杂组件创建的详细过程和繁琐细节都屏蔽起来,只把最简洁的使用界面展示给我们

配置factoryBean类

package com.huang.factoryBean;import org.springframework.beans.factory.FactoryBean;public class factoryBean implements FactoryBean<User> {@Overridepublic User getObject() throws Exception {
//可以在这类中完成实体类的操作,将具体的操作封装在该方法中User user = new User();user.setName("hfw");return user;}@Overridepublic Class<?> getObjectType() {return User.class;}
}

 将该类在bean-factoryBean.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"><bean id="factoryBean" class="com.huang.factoryBean.factoryBean"></bean>
</beans>

进行测试,最终我们会发现在获取该bean时会返回User对象,完成封装。

Spring 开启自动扫描的方法

在bean.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:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!--开启组件扫描功能-->
<!--    base-package对应的就是要扫描注解的包路径--><context:component-scan base-package="com.huang"><!--        要排除的扫描注解的如路径-->
<!--        <context:exclude-filter type="annotation" expression="xxx.xxx.xxx"/>-->
<!--要排除扫描注解的类--><!--<context:exclude-filter type="assignable" expression="xxx.xxx.xxx"/>--><!--        仅扫描的包路径-->
<!--        <context:include-filter type="annotation" expression="xxx.xxx.xxx"/>--><!--        仅扫描的类--><!--<context:include-filter type="assignable" expression="xxx.xxx.xxx"/>--></context:component-scan>
</beans

spring中的@Autowired可以使用在 属性上,set方法上,构造方法上,构造方法的形参上,注解上

如果类中只存在一个构造方法时,可以省略@Autowired

如果在使用@Autowired的属性是接口且存在多个实现类的话,我们就需要使用@Qualifier(value="bean中对应的id"),我们可以将@Autowired当作ByType,@Resource当作ByName,如果Autowired要达到ByNam的效果就要配合@Qualifier使用 

 实现全注解开发

创建配置类

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

使用ApplicationContext的实现类AnnotationConfigApplicationContext

 @org.junit.jupiter.api.Testvoid test2() {ApplicationContext context = new AnnotationConfigApplicationContext(Configuration.class);}

手写IoC

  Java反射回顾测试例子

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;public class reflectTest {@Testpublic void Test1() throws Exception {//直接通过.class获取该类的classClass clazz1 = User.class;//通过new出来的对象调用getClass方法Class clazz2 = new User().getClass();//通过class.forName获取Class对象Class clazz3 = Class.forName("com.huang.User");//创建一个实体类后续需要使用User user = new User();System.out.println("############通过反射获取构造器############");//通过反射获取公共的构造器Constructor[] constructors = clazz1.getConstructors();for (Constructor item : constructors) {System.out.println(item.getName());//使用构造器的newInstance()创建实例}
//        System.out.println("############=############");System.out.println("############获取所有的构造器############");//通过反射获取私有和公有的构造器Constructor[] declaredConstructors = clazz1.getDeclaredConstructors();for (Constructor item : declaredConstructors) {System.out.println(item.getName());}System.out.println("############获取类的属性############");Field[] fields = clazz1.getFields();System.out.println("因为属性全部为私有,所以打印为空");for (Field item : fields) {System.out.println(item.getName());}System.out.println("############获取类的私有和公共的属性############");Field[] declaredFields = clazz1.getDeclaredFields();for (Field item : declaredFields) {System.out.println(item.getName());if(item.getName().equals("name")) {//设置访问权限为true,这样我们才可以设置对应的属性item.setAccessible(true);item.set(user, "秃狼");System.out.println("设置的新值为:" + user.getName());}if(item.getName().equals("age")) {//设置访问权限为true,这样我们才可以设置对应的属性item.setAccessible(true);item.set(user, 21);System.out.println("设置的新值为:" + user.getAge());}}System.out.println("############获取类的方法############");Method[] methods = clazz1.getMethods();for (Method item : methods) {System.out.println(item);}System.out.println("############获取类的私有和公共的方法############");Method[] declaredMethods = clazz1.getDeclaredMethods();for (Method item : declaredMethods) {System.out.println(item.getName());if(item.getName().equals("tostring")) {//因为该方法是私有类型的,所以需要设置权限//这里使用了私有方法item.setAccessible(true);System.out.println("============");item.invoke(user);System.out.println("=============");}}System.out.println("############=############");}
}

这里的User为简单的类,可以自行创建

public class User {private String name;private int age;public User(String name, int age) {this.name = name;this.age = age;}public User() {}private User(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}private void tostring() {System.out.println("Name:" + this.name + ";" + "age:" + this.age);}
}

测试结果为下

 开始手写IoC

手写例子

这里设置的情况为每个类最多只有可以实现的接口,IoC为单例的情况。

创建两个注释:

 Bean(转载注释)

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;//设置作用域:作用在类上
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Bean {
}

rush(注入注释)

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;//设置作用域:设置为作用在属性上
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface rush {
}

 在包中创建三层架构:Dao,Service,Controller,分别创建一个接口和对应的Impl实现类。
 

这里的ApplicationContext就是包含一个getBean的接口,就是模仿Spring中ApplicationContext。

import com.huang.Annotation.Bean;
import com.huang.Annotation.rush;import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;public class AnnotationApplicationContext implements ApplicationContext{//bean的本质就是将对应的class和实例对象存放在map中,放和取就是通过对应的注解完成private Map<Class, Object> beanFactory = new HashMap<>();
//绝对路径的头路径private String rootPath;@Overridepublic Object getBean(Class clazz) {return beanFactory.get(clazz);}public AnnotationApplicationContext(String basePackage) {/*basePackage中的路径为指定类的当前路径,并且要进行格式转换后获取绝对路径*/String packageDirName = basePackage.replaceAll("\\.", "\\\\");try {//通过当前线程获取对应的绝对路径Enumeration<URL> dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);while (dirs.hasMoreElements()) {URL url = dirs.nextElement();/*因为获取的绝对路径中的"\"会被打印成"%",需要通过Decoder将绝对路径转为UTF-8的格式*/String filePath = URLDecoder.decode(url.getFile(), "utf-8");/*获取绝对路径头路径,方便后续的拆分,filePath.length() - packageDirName.length() - 1,正好就取到头路径部分*/rootPath = filePath.substring(0, filePath.length() - packageDirName.length() - 1);//装载beanthis.loadBean(new File(filePath));//注入属性this.loadRush();}} catch (Exception e) {e.printStackTrace();}}private void loadBean(File file) throws ClassNotFoundException, IllegalAccessException, InstantiationException {//进行判断插入的文件是否为文件夹if(file.isDirectory()) {//获取去子文件,如果没有就说明文件夹为空,直接返回空值File[] files = file.listFiles();if(files.length == 0 || files == null) {return ;}for (File child : files) {if(child.isDirectory()) {//如果子文件还是文件夹的话,就直接使用递归调用loadBean函数loadBean(child);} else {//将子文件的绝对路径设置截取为类路径String pathWithClass = child.getAbsolutePath().substring(rootPath.length());//获取类的路径后,需要判断是否为.class文件再进行操作if(pathWithClass.endsWith(".class")) {//如果是,就再将类路径进行格式转化String fullName = pathWithClass.replaceAll("\\\\", ".").replace(".class", "");//通过类路径获取反射Class<?> aClass = Class.forName(fullName);//判断该反射是否为接口的反射类,如果不是我们才进行判断类上是否有指定的注解if(!aClass.isInterface()) {//获取类上的注解,判断这些注解是否有指定的注解Bean annotation = aClass.getAnnotation(Bean.class);if(annotation != null) {//instance作为beanFactory的值Object instance = aClass.newInstance();//如果该类存在实现的接口就用接口作为键,这里就不考虑存在多个接口了if(aClass.getInterfaces().length > 0) {Class<?>[] interfaces = aClass.getInterfaces();//这里就考虑存在一个接口beanFactory.put(aClass.getInterfaces()[0], instance);} else {//如果不存在就之家用本类beanFactory.put(aClass, instance);}}}}}}} else {System.out.println("不是文件夹,输入有误");return ;}}private void loadRush() throws IllegalAccessException {//遍历mapSet<Map.Entry<Class, Object>> entries = beanFactory.entrySet();for (Map.Entry<Class, Object> entry : entries) {//获取实体类(这里就只考虑单例)Object obj = entry.getValue();Class key = obj.getClass();//获取所有的属性Field[] declaredFields = key.getDeclaredFields();for (Field field : declaredFields) {//设置访问权限field.setAccessible(true);//判断该属性是否有对应的注解rush annotation = field.getAnnotation(rush.class);if(annotation != null) {//就对实体类的属性进行赋值field.set(obj, beanFactory.get(field.getType()));//完成注入}}}}
}

在代码中 String filePath = URLDecoder.decode(url.getFile(), "utf-8")的作用是格式化路径,如果不加将会出现下面的情况。(/被%替代

 测试代码

//要到对自己写的包
import com.huang.ApplicationContext.AnnotationApplicationContext;
import com.huang.ApplicationContext.ApplicationContext;
import com.huang.Controller.UserController;public class TestUser {public static void main(String[] args) {ApplicationContext context = new AnnotationApplicationContext("com.huang");UserController userController = (UserController) context.getBean(UserController.class);userController.run();}
}

测试结果为下:

 最终完成手写IoC。

相关文章:

Spring IoC 深度学习

Io回顾 IoC 是 Inversion of Control 的简写&#xff0c;译为“控制反转”&#xff0c;它不是一门技术&#xff0c;而是一种设计思想&#xff0c;是一个重要的面向对象编程法则&#xff0c;能够指导我们如何设计出松耦合、更优良的程序。 Spring 通过 IoC 容器来管理所有 Jav…...

C语言从入门到精通第17天(指针和数组联用)

指针和数组联用 不同类型指针变量之间的区别数组的指针指针数组 不同类型指针变量之间的区别 在了解数组和指针联用之前&#xff0c;我们先对指针变量进行补充。我们对比一下int *p1和char *p2的区别&#xff1f; 相同点&#xff1a; 都是指针变量都是用来保存一个内存地址编…...

Android9.0 原生系统SystemUI下拉状态栏和通知栏视图之锁屏通知布局

1.前言 在9.0的系统rom定制化开发中,对于系统原生systemui的锁屏界面的功能也是非常重要的,所以在锁屏页面布局中,也是有通知栏布局的,所以接下来对于息屏亮屏 通知栏布局的相关流程分析,看下亮屏后锁屏页面做了哪些功能 2.原生系统SystemUI下拉状态栏和通知栏视图之锁…...

音视频八股文(10)-- mp4结构

介绍 mp4⽂件格式⼜被称为MPEG-4 Part 14&#xff0c;出⾃MPEG-4标准第14部分 。它是⼀种多媒体格式容器&#xff0c;⼴泛⽤于包装视频和⾳频数据流、海报、字幕和元数据等。&#xff08;顺便⼀提&#xff0c;⽬前流⾏的视频编码格式AVC/H264 定义在MPEG-4 Part 10&#xff09…...

python算法中的深度学习算法之深度信念网络(详解)

目录 学习目标: 学习内容: 深度信念网络 Ⅰ. 预训练 Ⅱ. 微调 学习目标: 一分钟掌握 python算法中的深度学习算法之深度信念网络 入门知识...

SPSS如何绘制常用统计图之案例实训?

文章目录 0.引言1.绘制简单条形图2.绘制分类条形图3.绘制分段条形图4.绘制简单线图5.绘制多重线图6.绘制垂直线图7.绘制简单面积图8.绘制堆积面积图9.绘制饼图10.绘制直方图11.绘制简单散点图12.绘制重叠散点图13.绘制矩阵散点图14.绘制三维散点图15.绘制简单箱图16.绘制分类箱…...

打动人心的故事 | 如何利用文案在Facebook上塑造品牌形象

在当今的数字营销时代&#xff0c;文案已经成为各大平台上不可或缺的元素之一。在Facebook上&#xff0c;一个好的文案能够为品牌带来巨大的曝光率和用户黏性&#xff0c;甚至可以改变用户对品牌的看法。那么&#xff0c;如何利用文案在Facebook上打动人心&#xff0c;塑造品牌…...

什么是模糊控制?

模糊控制设计原理 1、传统控制系统和模糊控制系统 传统控制系统结构&#xff1a; 控制目的&#xff1a;通过控制器调节控制信号u&#xff0c;使输出信号y达到要求 模糊控制系统结构&#xff1a; 与传统控制系统的差异&#xff1a;用模糊控制器FC&#xff08;Fuzzy Controller&…...

仿抖音开发需要注意的问题

一、版权问题 仿抖音开发需要注意版权问题&#xff0c;包括内容的版权和软件的版权。在开发的过程中&#xff0c;不要直接抄袭他人的作品&#xff0c;应该注重保护知识产权。 二、安全性问题 仿抖音开发需要重视应用的安全性问题&#xff0c;避免应用在使用过程中发生安全漏…...

如何根据期刊缩写查找期刊?

英文论文写作中&#xff0c;经常会插入参考文献。参考文献中的期刊名称&#xff0c;时常需要使用缩写。或者是手头有期刊缩写后的名称&#xff0c;但是有时候&#xff0c;查了半天也查不到期刊期刊全称&#xff0c;费时费力让人崩溃。今天就给各位学者老师总结一些查询期刊缩写…...

数据发送流程

在发送模式下&#xff0c;UART 的串行数据发送电路主要包括一个发送移位寄存器(TSR)&#xff0c;TSR 功能是将数据 逐个移位送出。待发数据必须先写到发送缓冲区中。 TXIFx 是发送中断标志位&#xff0c;可配置为发送缓冲区空或TSR 空。 数据的发送支持7bit 、8bit 或9bit 数据…...

堆及其应用

堆是一种基于树结构的数据结构&#xff0c;通常用于实现优先队列。堆分为最大堆和最小堆两种类型&#xff0c;最大堆的每个节点的值都大于等于其子节点的值&#xff0c;最小堆则相反&#xff0c;每个节点的值都小于等于其子节点的值。 基础算法操作包括&#xff1a; 1. 插入元…...

MySQL数据库备份脚本

PS&#xff1a;此脚本简单易懂&#xff0c;根据实际情况修改个别参数测试后即可使用&#xff0c;如有错误请指出&#xff01; 1.MySQL数据库备份脚本 #!/bin/bashuser pw ip dateYdate "%Y" date2date "%Y%m%d" date3date "%Y%m%d %H:%M" date…...

【2023 · CANN训练营第一季】应用开发深入讲解——第三章应用调试

学习资源 日志参考文档 应用开发FAQ 日志主要用于记录系统的运行过程及异常信息&#xff0c;帮助快速定位系统运行过程中出现的问题以及开发过程中的程序调试问题。 日志分为如下两大类&#xff1a; 系统类日志&#xff1a;系统运行产生的日志。主要包括&#xff1a; Contro…...

黎曼几何与黎曼流形

目录 0.黎曼几何 1. 欧几里得几何与黎曼几何的区别 2.黎曼流形 3.黎曼距离 4.切空间 5.黎曼均值 6. SPD矩阵如何形成黎曼流型 7.切线空间映射 8.同余变换和同余不变 9.黎曼对齐 科普性笔记&#xff0c;做了解&#xff0c;不深入。 0.黎曼几何 黎曼几何是一种基于欧几…...

lua | 运算符与字符串

目录 一、运算符 算数运算符 关系运算符 逻辑运算符 其他运算符 运算符优先级 二、字符串 转义字符 方法与用途 字符串截取 字符串大小转换 字符串查找与反转 字符串格式化 字符与整数的转换 匹配模式 本文章为笔者学习分享 学习网站&#xff1a;Lua 基本语法 | …...

NetBackup 10.2 新功能介绍:PostgreSQL 和 MySQL 自动化恢复达成

NetBackup 10.2 新功能介绍&#xff1a;PostgreSQL 和 MySQL 自动化恢复达成 原文来自&#xff1a;VERITAS 中文社区 2023-04-27 在执行恢复任务时&#xff0c;手动提取、更新数据库和实例并将其附加到 PostgreSQL 和 MySQL 是常规操作。而在最新的 NetBackup 10.2 版本中&am…...

ADRV9002官方例程开发过程中遇到的问题

开发环境&#xff1a;Vivado2021.2 HDL版本&#xff1a;hdl_2021_r2 GitHub - analogdevicesinc/hdl at hdl_2021_r2 no-OS版本&#xff1a;no_OS-2021_R2 GitHub - analogdevicesinc/no-OS at 2021_R2 &#xff08;PS&#xff1a;也可以用Vivado2019.1开发&#xff0c…...

Figma转换为sketch,分享这3款工具

在我们的设计工作中&#xff0c;我们经常会遇到各种各样的设计文件相互转换的问题。 你经常为此头疼吗&#xff1f;当你遇到Figma转换Sketch文件的问题时&#xff0c;你是如何解决的&#xff1f;Figma转换Sketch文件有工具吗&#xff1f; 根据众多设计师的经验&#xff0c;本…...

淘宝天猫1688京东商品详情API接口,封装接口可高并发

要提供商品详情数据需要知道具体的商品信息&#xff0c;但通常商品详情数据应包括以下内容&#xff1a; 商品名称&#xff1a;商品的名称&#xff0c;以方便顾客对其进行识别和区分。 商品描述&#xff1a;一段让顾客能够全面认识商品的描述。应能够有效地展示商品的特性、功能…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

华为OD机试-最短木板长度-二分法(A卷,100分)

此题是一个最大化最小值的典型例题&#xff0c; 因为搜索范围是有界的&#xff0c;上界最大木板长度补充的全部木料长度&#xff0c;下界最小木板长度&#xff1b; 即left0,right10^6; 我们可以设置一个候选值x(mid)&#xff0c;将木板的长度全部都补充到x&#xff0c;如果成功…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文通过代码驱动的方式&#xff0c;系统讲解PyTorch核心概念和实战技巧&#xff0c;涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...

stm32wle5 lpuart DMA数据不接收

配置波特率9600时&#xff0c;需要使用外部低速晶振...

spring Security对RBAC及其ABAC的支持使用

RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型&#xff0c;它将权限分配给角色&#xff0c;再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...