springboot 自动装配和bean注入原理及实现
装配:创建bean,并加入IOC容器。
注入:创建bean之间的依赖关系。
1、类自动装配
SpringBoot 自动装配使得开发人员可以轻松地搭建、配置和运行应用程序,而无需手动管理大部分的 bean 和配置。
Spring Boot 的自动装配机制与模块化和复用化密切相关,它们之间存在着相互促进和互补的关系。
模块化:
Spring Boot 通过 Spring Starter 的方式提供了一种模块化的解决方案。每个 Starter 都是一个独立的模块,它包含了特定功能的配置、依赖和自动装配。
开发者可以根据项目的需求选择性地引入需要的 Starter,从而实现功能上的模块化。这使得项目结构更清晰、功能更独立,并且可以根据需求进行定制和组合。
同时,Spring Boot 本身也是一个模块化的框架,它将各种功能划分为不同的模块,如 Web、数据访问、安全等,使得开发者能够根据需要选择性地引入和使用这些功能模块。
复用化:
Spring Boot 的自动装配机制大大提高了代码的复用性。通过自动扫描和自动装配,Spring Boot 能够将各种功能模块自动集成到应用程序中,避免了重复编写和配置的工作。
Starter 的设计也是为了提高代码的复用性。开发者可以将常用的功能打包成 Starter,供其他项目引入和使用,从而避免了重复开发相似的功能。
此外,Spring Boot 的约定大于配置的原则也促进了代码的复用。通过统一的项目结构、配置规范和命名规范,开发者能够更容易地理解和使用他人编写的代码,提高了代码的可维护性和可复用性。
总的来说,Spring Boot 的自动装配机制使得模块化和复用化更加便捷和高效。开发者可以根据项目的需求选择性地引入功能模块,同时也可以将常用的功能封装成 Starter,以供其他项目复用。
这种模块化和复用化的设计理念使得 Spring Boot 在开发中得到了广泛的应用和认可。
1.1 自动装配原理(那些bean会被自动装配)
SpringBoot 会根据定义在 classpath 下的类,自动给你生成一些 Bean,并且加载到 Spring 的 Context 中。
那么,它的原理是什么呢?哪些 Bean 可以自动装配到容器里面呢?
其实在 SpringBoot 内部,会读取 classpath 下 META-INF/spring.factories 文件中的所配置的类的全类名。
我们可以找到 key为 org.springframework.boot.autoconfigure.EnableAutoConfiguration 对应的值。
可以发现就是一系列的 xxxAutoConfiguration,随便找两个类看一下,就是标记了 @Configuration 的配置类,并且通过一些条件注解,来判断、决定哪些 Bean 应该自动注入到容器中。
⚠️注意:
在SpringBoot 2.7 版本后,spring.factories 方式已经被标记为废弃,
SpringBoot 2.7 版本后建议使用新的配置文件:
/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports ,
但是,在加载到时候,会同时加载这两个文件。
比如自己可以配置需要加入的bean并在类上使用@AutoConfiguration注解。包名和配置示例如下
可以通过条件注解的方式排除某些bean加载到容器中,节省启动时间和内存
1.2 自动装配的实现
1.2.1 自动装配实现
SpringBoot 是如何实现自动装配的,先看一个大概步骤:
-
1、 组件扫描(Component Scanning):Spring Boot 使用组件扫描来查找和注册标有特定注解的 bean。默认情况下,Spring Boot 将扫描主应用程序类所在的包及其子包下的所有类。标有 @Component、@Service、@Repository 和 @Controller 注解的类将被注册为 bean。
-
2、条件化的 bean 注册(Conditional Bean Registration):Spring Boot 使用条件化的 bean 注册来根据条件自动注册特定的 bean。这些条件可以基于环境属性、系统属性、类路径是否包含特定类等。当条件满足时,相应的 bean 将被注册到 Spring 的应用程序上下文中。
-
3、自动配置(Auto-Configuration):Spring Boot 基于类路径中的 jar 包和已配置的条件自动配置应用程序上下文。Spring Boot 提供了大量的自动配置类,这些类负责根据条件注册特定的 bean,以及设置应用程序的默认配置。这样,开发人员就无需手动配置大部分常见的 bean 和配置,而是可以依赖于 Spring Boot 的自动配置。图示如下
-
-
SpringBoot 会去扫描指定的配置类,然后通过条件判断是否加载 Bean。
1.2.2 向容器注入bean
主要方式见上面的自动装配,下来举例几个
2.2.1 @Component + @ComponentScan
SpringBoot启动类的@SpringBootApplication注解中就标注了 @ComponentScan注解,这个注解默认扫描当前包及其子包下的标注有@Component、@Controller、@Service、@Repository等的类加载到容器中。
2.2.2 @Import注解
2.2.3 @Configuration + @Bean
只需要在配置类上标注上@Configuration声明配置类,在某个方法上标注@Bean并返回一个需要注入的对象即可
@Configuration
public class MyBeanConfiguration {@Bean(name = "myBean")public MyBean initMyBean() {return new MyBean();}
}-------------------------------------------------@SpringBootApplication
@ComponentScan(basePackages = {"com.example.demo.*", "com.alibaba"}) // 需指明路径。
public class emptyDemoApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(emptyDemoApplication.class, args);Object myBean = context.getBean("myBean");System.out.println(myBean); // MyBean(filedA=null, fieldB=null)}
2.1.4 手动注入实现接口BeanDefinitionRegistryPostProcessor
我们知道SpringBean的生命周期中有很多前后置方法,整体上可以概括为普通类对象转化为beanDefinition再转化为spring中的bean这么三个阶段。
而Spring会在启动的AbstratApplicationContxt类中的refresh方法中执行
invokeBeanFactoryPostProcessors,这个方法中会回调所有实现
BeanDefinitionRegistryPostProcessor接口的钩子方法。
可以简单理解成beanDefinition加载完毕之后,会对beanDefinition进行后置处理。所以理论上实现BeanDefinitionRegistryPostProcessor接口就可以手动将bean注入到容器中。
下面举例以手动注入HashMap为例:
public class TestBeanProcessor {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();UptownBeanProcessor beanDefinitionRegistryPostProcessor = new UptownBeanProcessor();applicationContext.addBeanFactoryPostProcessor(beanDefinitionRegistryPostProcessor);applicationContext.refresh();Object bean = applicationContext.getBean("test_map");System.out.println(bean);}
}
class UptownBeanProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(HashMap.class).getBeanDefinition();registry.registerBeanDefinition("test_map", beanDefinition);}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
}
1.3 自动装配的核心注解
Spring Boot 实现自动装配的几个核心注解包括:
- @SpringBootApplication:这是一个组合注解,相当于同时使用了 @Configuration、@EnableAutoConfiguration 和 - @ComponentScan 注解。它标记了主应用程序类,并告诉 Spring Boot 开始组件扫描、自动配置和装配。
- @EnableAutoConfiguration:该注解用于启用 Spring Boot 的自动配置功能。它会根据应用程序的依赖关系和当前环境,自动注册所需的 bean。
- @ComponentScan:该注解用于启用组件扫描,以便 Spring Boot 可以自动发现和注册标有 @Component、@Service、@Repository 和 @Controller 注解的类。
- @ConditionalOnClass 和 @ConditionalOnMissingClass:这两个条件化注解用于根据类路径上是否存在特定的类来决定是否注册 bean。@ConditionalOnClass 在类路径上存在指定类时生效,而 @ConditionalOnMissingClass 在类路径上不存在指定类时生效。
- @ConditionalOnBean 和 @ConditionalOnMissingBean:这两个条件化注解用于根据是否存在特定的 bean 来决定是否注册 bean。@ConditionalOnBean 在容器中存在指定的 bean 时生效,而 @ConditionalOnMissingBean 在容器中不存在指定的 bean 时生效。
- @ConditionalOnProperty:该条件化注解用于根据配置属性的值来决定是否注册 bean。它可以根据配置文件中的属性值来决定是否启用或禁用特定的 bean。
这些注解结合在一起,为 Spring Boot 提供了自动装配的能力。
从源码层面来说,Spring Boot 自动装配的核心实现,主要就是依赖 @SpringbootApplication 这个注解,它又是个组合注解,由3部分组成:
- @SpringBootConfiguration,标注是一个配置类
- @EnableAutoConfiguration,开启自动装配
@AutoConfigurationPackage,指定默认的包规则,将主程序类所在包及其子包下的组件扫描到容器里
@Import(AutoConfigurationImportSelector.class),导入AutoConfigurationImportSelector,并通过 selectImports 方法读取 META-INF/spring.factories 文件中配置的全类名,并按照条件过滤,注入需要的 bean - @ComponentScan,配置扫描路径,用来加载 bean
1.3.1 条件注解
SpringBoot条件注解
Spring 为我们提供了条件化注解,可以让我们控制 bean 在某种条件下才加载,主要就是 @Conditional 注解,通过指定条件,然后根据条件结果执行。
Spring 还为我们提供了一些已有的条件可以让我们直接使用:
@ConditionalOnClass:当类路径中存在指定的类时生效。
@ConditionalOnMissingClass:当类路径中不存在指定的类时生效。
@ConditionalOnBean:当容器中存在指定的 Bean 时生效。
@ConditionalOnMissingBean:当容器中不存在指定的 Bean 时生效。
@ConditionalOnProperty:当指定的配置属性存在且值符合条件时生效。
@ConditionalOnResource:当类路径下存在指定资源文件时生效。
@ConditionalOnWebApplication:当应用是 Web 应用时生效。
@ConditionalOnNotWebApplication:当应用不是 Web 应用时生效。
1.4 如何自定义一个 SpringBoot starter?
Spring Boot 的自动装配机制使得模块化和复用化更加便捷和高效。
开发者可以根据项目的需求选择性地引入功能模块,同时也可以将常用的功能封装成 Starter,以供其他项目复用。
SpringBoot 这种模块化和复用化的设计理念使得 Spring Boot 在开发中得到了广泛的应用和认可。
1.4.1 社区常用starter
SpringBoot Starter用于简化开发过程并提供各种功能的集成,Spring Boot 社区提供了许多常用的 Starter,常用的如下:
- spring-boot-starter-web:用于构建 Web 应用程序的 Starter,包括 Spring MVC、Embedded Tomcat、Jackson、Validation 等。
- spring-boot-starter-data-jpa:用于集成 Spring Data JPA 和 Hibernate 的 Starter,用于访问和操作关系型数据库。
- spring-boot-starter-data-mongodb:用于集成 Spring Data MongoDB 的 Starter,用于访问和操作 MongoDB 数据库。
- spring-boot-starter-security:用于集成 Spring Security 的 Starter,提供身份验证和授权功能。
- spring-boot-starter-test:用于测试 Spring Boot 应用程序的 Starter,包括 JUnit、Spring Test、Spring Boot Test 等。
- spring-boot-starter-actuator:用于监控和管理 Spring Boot 应用程序的 Starter,包括健康检查、指标、日志级别设置等。
- spring-boot-starter-log4j2:用于集成 Log4j2 日志框架的 Starter,用于记录应用程序日志。
- spring-boot-starter-mail:用于集成邮件发送功能的 Starter,包括 JavaMail 和 Spring Framework 的邮件支持。
- spring-boot-starter-cache:用于集成缓存支持的 Starter,包括 Spring 缓存抽象和常见的缓存实现,如 Ehcache、Redis、Caffeine 等。
- spring-boot-starter-actuator:用于添加生产就绪功能,如指标、健康检查、审计、HTTP追踪等。
1.4.2 自定义starter
基本的结构图
自定义步骤如下,一般是一个新建的module
1、新建 SpringBoot 项目,引入 SpringBoot 相关依赖
2、创建 @Configuration 配置类,在配置类里面声明要注入的 Bean,还可以结合 @Conditional 条件注解,按需加载
@Configuration
@ConditionalOnClass(MyStarterService.class)
public class MyStarterAutoConfiguration {// 自动配置的内容,例如注册 Bean、初始化等
}
3、在项目的 resources 包下创建 META-INF/spring/ 文件,并且配置类的全限定名
4、其他项目或者模块引入即可
<dependency><groupId>com.warm</groupId><artifactId>custom-starter</artifactId><version>0.0.1-SNAPSHOT</version>
</dependency>
2、bean的注入实现
就是将一个对象注入到另一个对象中,以便它们可以相互协作创建依赖关系,提高了代码的可维护性和可读性
2.1 注入原理
2.2 注入的几种实现方式
2.2.1 通过属性(字段)注入
注解@Autowired或@Resource
字段注入是一种不太常用的注入方式,它使用@Autowired或者@Resource注解直接将需要注入的Bean注入到类的字段中。下面是一个示例:
@Autowiredprivate ApplicationContext applicationContext;
-
优点
代码少,简洁明了。
新增依赖十分方便,不需要修改原有代码 -
缺点
容易出现空指针异常。
空指针异常不是必现的,与bean的实例化顺序有关。有时,把依赖的bean改个名字就会报空指针异常。
会出现循环依赖的隐患。
2.2.2 通过setter方法注入
Setter方法注入是另一种常用的注入方式。开发者可以在Bean类中定义Setter方法,并使用@Autowired注解将需要注入的Bean作为参数传入。Spring容器会自动调用这些Setter方法,并将Bean注入到它们中。下面是一个示例:
private AdminUserApi adminUserApi;//@Autowired是用在成员变量的Setter函数上。@Autowiredpublic void setAdminUserApi(AdminUserApi adminUserApi) {this.adminUserApi = adminUserApi;}
但是我的通过setter方法注入为null,我通过setter方法+对象传递
if (handler instanceof AbstractSliderDesensitizationHandler) {((AbstractSliderDesensitizationHandler<?>) handler).setAdminUserApi(adminUserApi);}
2.2.3 通过构造函数+final注入
是Springboot最为推荐的一种使用方式。
构造函数注入是最常用的注入方式之一。开发者可以在Bean类的构造函数中声明需要注入的Bean,并在应用程序启动时,Spring容器会自动将这些Bean注入到构造函数中。下面是一个简单的示例:
@Component
@SuppressWarnings("rawtypes")
public class StringDesensitizeSerializer extends StdSerializer<String> implements ContextualSerializer {private final ApplicationContext applicationContext;private final AdminUserApi adminUserApi;//@Autowiredpublic StringDesensitizeSerializer(ApplicationContext applicationContext, AdminUserApi adminUserApi) {super(String.class);this.applicationContext = applicationContext;this.adminUserApi = adminUserApi;}
结果注入成功,不是null
重点
- 不能提供无参构造方法,否则Springboot默认会加载无参的构造方法,Bean实例对象会为null
- Springboot官方建议使用final来修饰成员变量,然后通过构造方法来进行注入。原因:final修饰的成员变量是不能够被修改的;不加final虽然也能注入Bean,但是若被其他人修改为null,可能会导致不必要的问题,所以最好是加final。
若手工写构造方法觉得麻烦,也可以使用lombok中的 @RequiredArgsConstructor
@RequiredArgsConstructor
public class StringDesensitizeSerializer extends StdSerializer<String> implements ContextualSerializer {private final ApplicationContext applicationContext;private final AdminUserApi adminUserApi;}
2.2.4 通过Qualifier注解
该 注解可以指定注入的实现类(某接口多个 实现类)
@Service
public class MyService {private final MyRepository repository;@Autowiredpublic MyService(@Qualifier("myRepositoryImpl") MyRepository repository) {this.repository = repository;}
}
3、名词介绍
- 定义:Bean 是在 Spring 容器中被实例化、管理和维护的对象。一个 Bean 可以是任何普通的 Java 对象,例如 POJO、Service、Respository、Controller 等等。将一个类声明为 Bean 的方式可以是在类级别上使用 ‘@Component’ 注解或其派生注解(‘@Service’、‘@Repository’、‘@Controller’等),也可以是通过配置文件进行显式的声明。
-
实例化:Spring 容器负责实例化 Bean。当应用程序启动时,Spring 容器会根据配置信息或注解扫描的结果,找到并实例化所有被标记为 Bean 的类,并将它们加入容器中。实例化的过程由 Spring 的 IoC 容器负责。
-
管理:一旦 Bean 被实例化,Spring 容器将负责管理 Bean 的生命周期和依赖关系。它会根据配置文件或注解的信息,自动解决 Bean 之间的依赖关系,确保在需要的时候正确的注入依赖。Spring 容器还会负责销毁不再需要的 Bean。
-
依赖注入:依赖注入是 Spring 框架的一个重要特性,它允许通过自动或显式配置的方式将 Bean 的依赖项注入到其它 Bean 中。依赖注入可以通过构造函数注入、Setter 方法注入或字段注入的方式实现,其中最常见的是使用 ‘@Autowired’注解进行注入。
-
作用域:Spring 框架提供了多种作用域(scope)来管理 Bean 的生命周期。常见的作用域包括单例(Singleton)、原型(Prototype)、会话(Session)、请求(Request)等。默认情况下,Bean 是单例的,即每个容器中只存在一个实例。但可以根据需要配置其它作用域。
@Component // 默认为单例 -
自动装配:Spring Boot 支持自动装配(Auto - wiring),它能够根据类型或名称自动解析和注入依赖关系。通过在需要注入的字段、构造函数或 Setter 方法上使用 ‘@Autowired’ 注解,Spring 容器会自动查找并注入对应的 Bean。
@Component
public class MyService {
@Autowired
private MyBean myBean;// 使用myBean的代码…
}
总的来说,Bean 是 Spring 框架中被实例化、管理和维护的对象。通过在类上使用 ‘@Component’ 注解或其派生注解,将一个类声明为 Bean,并将其交给 Spring 容器处理。Spring 容器负责实例化、管理和维护 Bean 的生命周期和依赖关系。通过依赖注入和自动装配,应用程序可以方便的使用和管理 Bean。
相关文章:

springboot 自动装配和bean注入原理及实现
装配:创建bean,并加入IOC容器。 注入:创建bean之间的依赖关系。 1、类自动装配 SpringBoot 自动装配使得开发人员可以轻松地搭建、配置和运行应用程序,而无需手动管理大部分的 bean 和配置。 Spring Boot 的自动装配机制与模块…...

解决Redis缓存穿透(缓存空对象、布隆过滤器)
文章目录 背景代码实现前置实体类常量类工具类结果返回类控制层 缓存空对象布隆过滤器结合两种方法 背景 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库 常见的解决方案有两种,分别…...

初探Flink的序列化
Flink中的序列化应用场景 程序通常使用(至少)两种不同的数据表示形式[2]: 1. 在内存中,数据保存在对象、结构体、列表、数组、哈希表和树等结构中。 2. 将数据写入文件或通过网络发送时,必须将其序列化为字节序列。 从内存中的表示到字节序列…...

QT 机器视觉 (3. 虚拟相机SDK、测试工具)
本专栏从实际需求场景出发详细还原、分别介绍大型工业化场景、专业实验室场景、自动化生产线场景、各种视觉检测物体场景介绍本专栏应用场景 更适合涉及到视觉相关工作者、包括但不限于一线操作人员、现场实施人员、项目相关维护人员,希望了解2D、3D相机视觉相关操作…...

1分钟解决Excel打开CSV文件出现乱码问题
一、编码问题 1、不同编码格式 CSV 文件有多种编码格式,如 UTF - 8、UTF - 16、ANSI 等。如果 CSV 文件是 UTF - 8 编码,而 Excel 默认使用的是 ANSI 编码打开,就可能出现乱码。例如,许多从网络应用程序或非 Windows 系统生成的 …...

基于SpringBoot+Vue的仓库管理系统【前后端分离】
基于SpringBootVue的仓库管理系统设计与实现 摘要 仓库管理系统在现代企业物流中具有重要作用,能够有效提高库存管理效率,优化资源配置。本系统采用Spring Boot作为后端框架,Vue作为前端框架,通过前后端分离的开发模式构建一个现代…...

vue和django接口联调
vue访问服务端接口 配置跨域 前端跨域 打开vite.config.js,在和resolve同级的地方添加配置。 proxy代表代理的意思 "/api"是以/api开头的路径走这个配置 target代表目标 changeOrigin: true,是开启跨域请求 rewrite是编辑路径。 (path) > pa…...

2-141 怎么实现ROI-CS压缩感知核磁成像
怎么实现ROI-CS压缩感知核磁成像,这个案例告诉你。基于matlab的ROI-CS压缩感知核磁成像。ROI指在图像中预先定义的特定区域或区域集合,选择感兴趣的区域,通过减少信号重建所需的数据来缩短信号采样时间,减少计算量,并在…...

开源库 FloatingActionButton
开源库FloatingActionButton Github:https://github.com/Clans/FloatingActionButton 这个库是在前面这个库android-floating-action-button的基础上修改的,增加了一些更强大和实用的特性。 特性: Android 5.0 以上点击会有水波纹效果 可以选择自定义…...

技术选型不当对项目的影响与补救措施
在项目管理中,初期技术选型与项目需求不匹配的情况并不罕见,这可能导致项目延误、成本增加和最终成果的不理想。补救的关键措施包括:重新评估技术选型、加强团队沟通、实施有效的需求管理以及建立持续的反馈机制。其中,重新评估技…...
Spring的核心类: BeanFactory, ApplicationContext 笔记241103
Spring的核心类: BeanFactory, ApplicationContext, ConfigurableApplicationContext, WebApplicationContext, WebServerApplicationContext, ClassPathXmlApplicationContext, FileSystemXmlApplicationContext, XmlWebApplicationContext, AnnotationConfigServletWebServer…...
UE5移动端主要对象生命周期及监听
1、GameInstance 1、首先加载GameInstance,全局唯一,切换Map也是唯一的,用于做一些全局操作,比如监听Map加载,监听App进入前台、退出后台 // Fill out your copyright notice in the Description page of Project Settings.#include "Core/Base/MyGameInstance.h&q…...

LLM | 论文精读 | CVPR | SelTDA:将大型视觉语言模型应用于数据匮乏的视觉问答任务
论文标题:How to Specialize Large Vision-Language Models to Data-Scarce VQA Tasks? Self-Train on Unlabeled Images! 作者:Zaid Khan, Vijay Kumar BG, Samuel Schulter, Xiang Yu, Yun Fu, Manmohan Chandraker 期刊:CVPR 2023 DOI…...

kafka里的consumer 是推还是拉?
大家好,我是锋哥。今天分享关于【kafka里的consumer 是推还是拉?】面试题?希望对大家有帮助; kafka里的consumer 是推还是拉? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在Kafka中,消费者&…...

针对物联网边缘设备基于EIT的手部手势识别的1D CNN效率增强的组合模型压缩方法
论文标题:Combinative Model Compression Approach for Enhancing 1D CNN Efficiency for EIT-based Hand Gesture Recognition on IoT Edge Devices 中文标题:针对物联网边缘设备基于EIT的手部手势识别的1D CNN效率增强的组合模型压缩方法 作者信息&a…...
商品满减、限时活动、折扣活动的计算最划算 golang
可以对商品的不同活动(如满减、限时价和折扣)进行分组,并在购物车中显示各个活动标签下的最优价格组合。以下代码将商品按活动类别进行分组计算,并输出在购物车中的显示信息。 package mainimport ("fmt""math&qu…...

vue3 + ts + element-plus 二次封装 el-table
一、实现效果: (1)数据为空时: (2)有数据时:存在数据合并;可自定义表头和列的内容 (3)新增行: (4)删除行: &a…...
python传递json参数给php
python传递json参数给php 在Python中,你可以使用requests库来发送JSON数据给一个PHP脚本。以下是一个简单的例子: 首先,安装requests库(如果你还没有安装的话): pip install requests 然后,…...

2.若依vue表格数据根据不同状态显示不同颜色style
例如国标显示蓝色,超标是红色 使用是蓝色,未使用是绿色 <el-table-column label"外卖配送是否完成评价" align"center" prop"isOverFlag"> <template slot-scope"scope"> …...

JZ2440开发板——LCD
以下内容源于韦东山嵌入式课程的学习与整理,如有侵权请告知删除。 之前在博文中学习过LCD(SoC是S5PV210),作为对比,本文学习S3C2440这款SoC的LCD方面的内容。主要涉及以下三个内容: 一、LCD的硬件原理 1.…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...

三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...