Spring基础(3):复习
为了让大家更容易接受我的一些观点,上一篇很多笔墨都用在了思路引导上,所以导致文章可能比较臃肿。
这一篇来总结一下,会稍微精简一些,但整体趣味性不如第二篇。
(上一篇说过了,目前介绍的2种注入方式的说法其实不够准确,后面源码分析时再详细介绍)
主要内容:
- 如何把对象交给Spring管理
- 依赖注入
- 自动装配
- <bean>、@Component还是@Bean
- 聊一聊@ComponentScan
如何把对象交给Spring管理
首先明确2个概念:Spring Bean和Java Object。
在Spring官方文档中,Bean指的是交给Spring管理、且在Spring中经历完整生命周期(创建、赋值、各种后置处理)的Java对象。
Object指的是我们自己new的、且没有加入Spring容器的Java对象。

笼统地讲,要把对象交给Spring管理大概有3种方式(其他方式以后补充):
- XML配置:<bean>
- 注解开发:@Component
- 配置类:@Configuration+@Bean
这里要稍微强调以下几点:
首先,XML配置方式必须搭配ClassPathXmlApplicationContext,并把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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 在xml中描述类与类的配置信息 --><bean id="person" class="com.bravo.xml.Person"><property name="car" ref="car"></property></bean><bean id="car" class="com.bravo.xml.Car"></bean>
</beans>
public class Test {public static void main(String[] args) {// 由于是XML配置方式,对应的Spring容器是ClassPathXmlApplicationContext,传入配置文件告知Spring去哪读取配置信息ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-context.xml");// 从容器中获取PersonPerson person = (Person) applicationContext.getBean("person");System.out.println(person);}
}

其次,所谓的注解开发不是说只要打上@Component注解,Spring就会把这个注解类解析成BeanDefinition然后实例化放入容器,必须配合注解扫描。
开启扫描的方式有2种:
- <context:component-scan>(XML+注解)
- @ComponentScan(@Configuration配置类+注解)
大家可以把注解开发等同于@Component,只不过这个注解的解析必须开启扫描。所以,在我眼中@Component其实只是半吊子,必须依附于XML或者@Configuration配置类。

最后,狭隘的JavaConfig风格可以等同于@Configuration+@Bean。此时,配置类上面的@ComponentScan并不是必须的。这取决于你是否要另外扫描@Component注解。一旦加了@ComponentScan,其实就是JavaConfig+注解了。
@Configuration //表示这个Java类充当XML配置文件
public class AppConfig {@Beanpublic Person person(){Person person = new Person();person.setCar(new Benz());return person;}
}
public class Test {public static void main(String[] args) {// AnnotationConfigApplicationContext专门搭配@Configuration配置类ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);// 从容器中获取PersonPerson person = (Person) applicationContext.getBean("person");System.out.println(person);}
}

3种编程风格其实指的是把Bean交给Spring管理的3种方式:
- <bean>
- @Component
- @Configuration+@Bean
至此,我们已经知道如何把Bean交给IOC。接下来,我们聊一聊DI。
依赖注入
虽然注入方式不止两种,但我们还是暂时按照两种方式复习
- setter方法注入
- 构造方法注入
setter方法注入
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 在xml中描述类与类的配置信息 --><bean id="person" class="com.bravo.xml.Person"><!-- property标签表示,让Spring通过setter方法注入--><property name="car" ref="car"></property></bean><bean id="car" class="com.bravo.xml.Car"></bean></beans>
Person
public class Person {// Person依赖Carprivate Car car;// setter方法public void setCar(Car car) {this.car = car;System.out.println("通过setter方法注入...");}@Overridepublic String toString() {return "Person{" +"car=" + car +'}';}
}
Car
public class Car {
}
<bean>中配置<property>,则类中必须提供setter方法。因为<property>等于告诉Spring调用setter方法注入。
构造方法注入
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 在xml中描述类与类的配置信息 --><bean id="person" class="com.bravo.xml.Person"><!-- constructor-arg标签表示,让Spring通过构造方法注入--><constructor-arg ref="car"></constructor-arg></bean><bean id="car" class="com.bravo.xml.Car"></bean></beans>
Person
public class Person {// Person依赖Carprivate Car car;// 有参构造public Person(Car car){this.car = car;System.out.println("通过构造方法注入...");}@Overridepublic String toString() {return "Person{" +"car=" + car +'}';}
}
<bean>中配置<constructor-arg>,则类中必须提供对应参数列表的构造方法。因为<constructor-arg>等于告诉Spring调用对应的构造方法注入。
什么叫对应参数列表的构造方法?比如上面配置的
<constructor-arg ref="car"></constructor-arg>
则类中必须提供
public Person(Car benz){this.car = benz;
}
参数多一个、少一个都不行,Spring只会找这个构造方法,找不到就报错!
自动装配
我们发现上面XML的依赖注入有点累赘。比如
Person
public class Person {// Person依赖Carprivate Car car;// setter方法public void setCar(Car car) {this.car = car;System.out.println("通过setter方法注入...");}@Overridepublic String toString() {return "Person{" +"car=" + car +'}';}
}
其实类结构已经很好地描述了依赖关系:Person定义了Car字段,所以Person依赖Car。
此时在<bean>中再写一遍
<!-- 在xml中描述类与类的配置信息 -->
<bean id="person" class="com.bravo.xml.Person"><!-- property标签表示,让Spring通过setter方法注入--><property name="car" ref="car"></property>
</bean>
<bean id="car" class="com.bravo.xml.Car"></bean>
就属于重复操作了。而且后期如果类结构发生改变,比如加了一个shoes字段,我们不仅要维护类结构本身,还要额外维护<bean>标签中的<property>。
针对这种情况,Spring提出了自动装配。我们分三种编程风格讨论。
1.XML的自动装配
在XML中,自动装配可以设置全局和局部,即:对所有bean起效,还是对单个bean起效
- 全局:default-autowire="byName"
- 局部:autowire="byName"
全局(XML文件中每一个bean都遵守byName模式的自动装配)
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"default-autowire="byName"><!-- 在xml中只定义bean,无需配置依赖关系 --><bean id="person" class="com.bravo.xml.Person"></bean><bean id="car" class="com.bravo.xml.Car"></bean></beans>
局部(只对当前<bean>有效)
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 在xml中只定义bean,无需配置依赖关系 --><bean id="person" class="com.bravo.xml.Person" autowire="byName"></bean><bean id="car" class="com.bravo.xml.Car"></bean></beans
XML的自动装配,与之前的依赖注入相比,只有XML文件不同:
- 去除之前依赖注入时配置的<property>或<constructor-arg>
- 加上全局或局部的自动装配属性
类结构要求还是和之前一样,该提供setter方法或者构造方法的,不能少。
自动装配共4种模式:
- byName
- byType
- constructor
- no
如果你选择byName或者byType,则需要提供setter方法。
如果你选择constructor,则需要提供给构造方法。

总之,对于XML而言,自动装配的作用是:只需写<bean>,不需要写<bean>里面的其他标签。
2.注解开发的自动装配
@Configuration //表示这个Java类充当XML配置文件
@ComponentScan("com.bravo.annotation")//开启注解扫描
public class AppConfig {
}
Person
@Component
public class Person {@Qualifier("benz")@Autowiredprivate Car car;@Overridepublic String toString() {return "Person{" +"car=" + car +'}';}
}
@Configuration配置类要搭配AnnotationConfigApplicationContext
public class Test {public static void main(String[] args) {// AnnotationConfigApplicationContext专门搭配@Configuration配置类ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);// 从容器中获取PersonPerson person = (Person) applicationContext.getBean("person");System.out.println(person);}
}
@Autowired默认是byType,如果找到多个相同的,会去匹配与当前字段同名的bean。没找到或者找到多个都会报错。
上面演示的是@Autowired作用于成员变量上,其实我们也可以把@Autowired加在构造方法上,它也会自动注入bean。
读完上面这句话两秒后,你意识到自己被骗了,于是反驳我:放你的屁,我从来没在构造方法上加@Autowired,而且即使不加,形参也能注入进来。
是的,确实不加也注入进来了。
在回答这个问题之前,我们先达成共识:不管我们new对象,还是Spring帮我们创建bean,都离不开构造方法。这一点没有异议吧?
当你的类中只有一个默认无参构造方法时,Spring实例化时没得选,只能用无参构造创建bean。但是,如果类中有两个构造方法,比如:
@Component
public class Person {private Car car;private Shoes shoes;public Person(Car benz) {this.car = benz;}public Person(Car benz, Shoes shoes){this.car = benz;this.shoes = shoes;}@Overridepublic String toString() {return "Person{" +"car=" + car +", shoes=" + shoes +'}';}}
此时,Spring会报错,因为它无法替你决定到底用哪个构造器创建bean。你要加上@Autowired,明确告诉Spring用哪个构造方法创建bean。
当然,放在setter方法上也可以注入进来。具体细节,会在分析自动装配底层源码时介绍。
3.JavaConfig的自动装配
其实没必要把JavaConfig再单独分出一类,因为它底层其实也是@Component。所以和在@Component里使用@Autowired是一样的。
AppConfig
@Configuration //表示这个Java类充当XML配置文件
@ComponentScan("com.bravo.javaconfig")//用来扫描Benz组件注入
public class AppConfig {//把benz注入进来,用来设置给person@Autowiredprivate Car benz;@Beanpublic Person person(){Person person = new Person();person.setCar(benz);return person;}
}
Person
public class Person {private Car car;public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "Person{" +"car=" + car +'}';}
}
<bean>、@Component还是@Bean
学习了把对象交给Spring管理的3种方式后,我们产生了疑惑:
<bean>、@Component和@Bean该如何取舍呢?
虽然@Bean和@Component都是注解,看起来是一家人,但其实@Bean和<bean>更接近。它俩的共同点是:
类文件和bean定义分开
什么意思呢?
打个比方:

@Component直接写在源码上,而bean标签和@Bean都是另写一个文件描述bean定义
直接写源码上面,有什么不好吗?
有好有坏。
好处是:相对其他两种方式,@Component非常简洁。
坏处是,如果你想要交给Spring管理的对象是第三方提供的,那么你无法改动它的源码,即无法在上面加@Component。更甚者,人家连源码都没有,只给了你jar包,怎么搞?
网上花里胡哨的对比一大堆,但个人觉得就这个是最重要的。以后遇到不好加@Component的,能想到@Bean或者<bean>就行了。
聊一聊@ComponentScan
我们都知道,@ComponentScan和XML中的<context:component-scan>标签功能相同,都是开启注解扫描,而且可以指定扫描路径。
AppConfig
@Configuration //表示这个Java类充当XML配置文件
@ComponentScan("com.bravo.javaconfig")
public class AppConfig {}
Person
@Component
public class Person {@Qualifier("benz")@Autowiredprivate Car car;@Overridepublic String toString() {return "Person{" +"car=" + car +'}';}
}
Benz
@Component
public class Benz implements Car {
}
Test
public class Test {public static void main(String[] args) {// AnnotationConfigApplicationContext专门搭配@Configuration配置类ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);// 从容器中获取PersonPerson person = (Person) applicationContext.getBean("person");System.out.println(person);}
}
目录结构

测试结果

接下来,我们做几个实验,来探讨一下@ComponentScan。
实验一:不写@ComponentScan
这个别试了,直接报错,因为压根没开启扫描,找不到Person。

报错:找不到Person,说明没扫描到
实验二:不指定路径,同包
AppConfig
@Configuration //表示这个Java类充当XML配置文件
@ComponentScan //删除basePackages,不指定路径
public class AppConfig {}
测试结果

还是能扫描到
实验三:指定路径,不同包
AppConfig
@Configuration //表示这个Java类充当XML配置文件
@ComponentScan("com.bravo.javaconfig")//扫描javaconfig包下的组件
public class AppConfig {}
把AppConfig类移到annotation包下,和Person等组件不同包:

测试结果

还是扫描到了,身在曹营心在汉,虽然配置类在annotation包下,但是路径指定了javaconfig
实验四:不指定路径,不同包
不试了,扫描不到。
总结
其实,背后的原理是下面这句代码:
// AnnotationConfigApplicationContext专门搭配@Configuration配置类
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
AnnotationConfigApplicationContext吃了AppConfig这个配置类后,会尝试去拿类上面的@ComponentScan注解:
- 有注解(开启扫描)
- 有路径:扫描指定路径
- 没路径:默认扫描当前配置类所在包及其子包下组件
- 没有注解(不开启扫描)
我们回头分析一下四个实验:
- 有注解
- 有路径:扫描指定路径(实验三:指定路径,不同包,但是指定的路径是对的)
- 没路径:默认扫描当前包及其子包下组件(实验二、四,默认扫描配置类所在包)
- 没有注解(不扫描)
- 报错(实验一:不写@ComponentScan)
@ComponentScan在SpringBoot中的应用
用过SpringBoot的朋友都知道,我们必须写一个启动类
@SpringBootApplication
public class SpringbootDemoApplication {public static void main(String[] args) {SpringApplication.run(SpringbootDemoApplication.class, args);}
}
而SpringBoot有一个不成文的规定:
所有的组件必须在启动类所在包及其子包下,出了这个范围,组件就无效了。
为什么会有这个规定呢?
我们来看一下启动类上唯一的注解@SpringBootApplication,发现它其实是一个组合注解:

@ComponentScan没有指定basePackages属性,也就是没有指定扫描路径。那么,按照上面的分析,默认扫描当前包及其子包下组件。
这就是上面不成文规定的背后原因。
相关文章:
Spring基础(3):复习
为了让大家更容易接受我的一些观点,上一篇很多笔墨都用在了思路引导上,所以导致文章可能比较臃肿。 这一篇来总结一下,会稍微精简一些,但整体趣味性不如第二篇。 (上一篇说过了,目前介绍的2种注入方式的说法其实不够…...
Java-Hbase介绍
1.1. 概念 base 是分布式、面向列的开源数据库(其实准确的说是面向列族)。HDFS 为 Hbase 提供可靠的 底层数据存储服务,MapReduce 为 Hbase 提供高性能的计算能力,Zookeeper 为 Hbase 提供 稳定服务和 Failover 机制,…...
【PHP】【Too few arguments to function Firebase\JWT\JWT::encode()。。。。。。。】
1.安装jwt composer require firebase/php-jwtuse Firebase\JWT\JWT;public function hello($name ThinkPHP5){$secret_key "YOUR_SECRET_KEY";$issuer_claim "THE_ISSUER";$audience_claim "THE_AUDIENCE";$issuedat_claim time(); // is…...
Centos系统上安装包(软件)时常用的命令wget、rpm、yum分别是什么意思和作用?
本文以在Centos上安装mysql-5.7.26的前三步为例,说明命令wget、rpm、yum的意思和作用。 安装mysql-5.7.26的步骤如下: 下载MySQL 5.7.26的RPM存储库文件: wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm安装R…...
虹科干货 | 旧电脑别急着扔,手把手教你搭建NAS系统存储照片
一、前期准备 我们的目的是让设备物尽其用,将旧电脑做成NAS存储系统后可以使用新电脑进行访问(Windows / Linux / IOS系统都可以访问)。在开始之前先来看看安装成功效果图吧! 1.设备准备 (1)一台旧电脑&am…...
python基础(Python高级特性(切片、列表生成式)、字符串的正则表达式、函数、模块、Python常用内置函数、错误处理)培训讲义
文章目录 1. Python高级特性(切片、列表生成式)a) 切片的概念、列表/元组/字符串的切片切片的概念列表切片基本索引简单切片超出有效索引范围缺省 扩展切片step为正数step为负数 b) 列表生成式以及使用列表生成式需要注意的地方概念举例说明1. 生成一个列…...
计讯物联高精度GNSS接收机:担当小型水库大坝安全监测解决方案的“护航者”
应用背景 水库大坝作为水利工程建筑物,承担着灌溉、发电、供水、生态等重任。一旦水库大坝发生安全事故,后果将不堪设想。因此,水库大坝的安全监测对保障水利工程顺利运行具有重要意义。 计讯物联作为水利行业专家型企业,多年来…...
信号发送与处理-上
问题 按下 Ctrl C 后,命令行中的前台进程会被终止。为什么??? 什么是信号? 信号是一种 "软件中断",用来处理异步事件 内核发送信号到某个进程,通知进程事件的发送事件可能来自硬件…...
[蓝桥杯 2022 省 A] 推导部分和
[蓝桥杯 2022 省 A] 推导部分和 题目描述 对于一个长度为 N N N 的整数数列 A 1 , A 2 , ⋯ A N A_{1}, A_{2}, \cdots A_{N} A1,A2,⋯AN,小蓝想知道下标 l l l 到 r r r 的部分和 ∑ i l r A i A l A l 1 ⋯ A r \sum\limits_{il}^{r}A_iA_{l}A…...
pytorch复现_UNet
什么是UNet U-Net由收缩路径和扩张路径组成。收缩路径是一系列卷积层和汇集层,其中要素地图的分辨率逐渐降低。扩展路径是一系列上采样层和卷积层,其中特征地图的分辨率逐渐增加。 在扩展路径中的每一步,来自收缩路径的对应特征地图与当前特征…...
定岗定编设计:企业职能部门定岗定编设计项目成功案例
一、客户背景及现状分析 某大型车辆公司隶属于某央企集团,建于20世纪60年代,是中国高速、重载、专用铁路车辆生产经营的优势企业,轨道车辆制动机研发制造的主导企业,是隶属于国内最大的轨道交通设备制造上市企业的骨干二级公司。公…...
鸿蒙原生应用开发-DevEco Studio本地模拟器的使用
使用Local Emulator运行应用/服务 DevEco Studio提供的Local Emulator可以运行和调试Phone、TV和Wearable设备的HarmonyOS应用/服务。在Local Emulator上运行应用/服务兼容签名与不签名两种类型的HAP。 Local Emulator相比于Remote Emulator的区别:Local Emulator是…...
QT blockingFilter blockingMap blockingMapped
blockingFilter 主要作用是筛选出符合条件的项值结果集,并与之替换原有序列列表 blockingMap 可以直接修改容器的每一项 blockingMapped 不直接修改容器的每一项,而是将处理后的结果返回一个新的容器 blockingMappedReduced ResultType QtConcurrent::blockingMappedRed…...
【ARFoundation学习笔记】平面检测
写在前面的话 本系列笔记旨在记录作者在学习Unity中的AR开发过程中需要记录的问题和知识点。难免出现纰漏,更多详细内容请阅读原文。 文章目录 平面检测属性可视化平面平面检测的开关控制显示与隐藏已检测平面 平面检测属性 AR中检测平面的原理:AR Fou…...
Python---ljust()--左对齐、rjust()--右对齐、center()--居中对齐
作用:返回原字符串左对齐、右对齐以及居中对齐,不足的使用 指定字符 进行填充。 ljust 左对齐 rjust 右对齐 center 居中对齐 类似于Excel、Word文档中的对齐。 基本语法: 字符串序列.ljust(长度, 填充字符) 案例: …...
spdk用户态块层详解
先通过回顾内核态的通用块层来详细介绍SPDK通用块层,包括通用块层的架构、核心数据结构、数据流方面的考量等。最后描述基于通用块层之上的两个特性:一是逻辑卷的支持,基于通用块设备的Blobstore和各种逻辑卷的特性,精简配置&…...
双通道 H 桥电机驱动芯片AT8833,软硬件兼容替代DRV8833,应用玩具、打印机等应用
上期小编给大家分享了单通道 H 桥电机驱动芯片,现在来讲一讲双通道的驱动芯片。 双通道 H 桥电机驱动芯片能通过控制电机的正反转、速度和停止等功能,实现对电机的精确控制。下面介绍双通道H桥电机驱动芯片的工作原理和特点。 一、工作原理 双通道 H 桥电…...
WPF布局与控件分类
Refer:WPF从假入门到真的入门 - 知乎 (zhihu.com) Refer:WPF从假入门到真的入门 - 知乎 (zhihu.com) https://www.zhihu.com/column/c_1397867519101755392 https://blog.csdn.net/qq_44034384/article/details/106154954 https://www.cnblogs.com/mq0…...
复杂逻辑的开发利器—Mendix快速实现AQL质量抽检
Mendix低代码开发平台适用于复杂的业务逻辑场景,这句话大家早有耳闻,本期小编就为您打开智慧之光,仅从AQL小侧面,来管窥一二——Mendix如何形成第五代编程语言,来完成数据逻辑与建模、业务算法逻辑与建模的。ÿ…...
RFID系统
目录 在物联网应用中有三项关键技术 读写器 电子标签 工作原理 阅读器的组成及作用: 电子标签的组成及作用: RFID系统的组成 接口方式 在物联网应用中有三项关键技术 在物联网应用中有三项关键技术 1、传感器技术:这也是计算机应用中…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...
如何配置一个sql server使得其它用户可以通过excel odbc获取数据
要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据,你需要完成以下配置步骤: ✅ 一、在 SQL Server 端配置(服务器设置) 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到:SQL Server 网络配…...
Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解
文章目录 一、开启慢查询日志,定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...
客户案例 | 短视频点播企业海外视频加速与成本优化:MediaPackage+Cloudfront 技术重构实践
01技术背景与业务挑战 某短视频点播企业深耕国内用户市场,但其后台应用系统部署于东南亚印尼 IDC 机房。 随着业务规模扩大,传统架构已较难满足当前企业发展的需求,企业面临着三重挑战: ① 业务:国内用户访问海外服…...
