『SpringBoot 源码分析』run() 方法执行流程:(2)刷新应用上下文-准备阶段
『SpringBoot 源码分析』run() 方法执行流程:(2)刷新应用上下文-准备阶段
- 基于 2.2.9.RELEASE
- 问题:当方法进行了注释标记之后,springboot 又是怎么注入到容器中并创建类呢?
- 首先创建测试主程序
package com.lagou;@SpringBootApplication//标注在类上说明这个类是`SpringBoot`的主配置类
public class SpringBootMytestApplication{public static void main(String[] args) {SpringApplication.run(SpringBootMytestApplication.class, args);}
}
- 创建测试 Controller
package com.lagou.controller;@RestController
public class TestController {@RequestMapping("/test")public String test(){System.out.println("源码环境构建成功...");return "源码环境构建成功";}
}
准备阶段
- 当准备完成应用上下文环境,以及应用上下文以后,需要为应用上下文做个准备阶段,简单来说其实就是要配置应用上下文,把需要的类装配上
public class SpringApplication {...public ConfigurableApplicationContext run(String... args) {...try {// 将运行时参数封装ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 构造应用上下文环境ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);// 处理需要忽略的 BeanconfigureIgnoreBeanInfo(environment);// 打印 bannerBanner printedBanner = printBanner(environment);// 刷新应用上下文前的准备阶段context = createApplicationContext();// 实例化 SpringBootExceptionReporter.class,用来支持报告关于启动的错误exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,new Class[] { ConfigurableApplicationContext.class }, context);// 1. 刷新应用上下文前的准备阶段prepareContext(context, environment, listeners, applicationArguments, printedBanner);...}catch (Throwable ex) {...}...}
}
- 在对应用上下文进行处理时,主要执行了下面几步的装配
- 把上下文环境设置到应用上下文中
- 执行容器后置处理
- 把应用上下文交给 SpringApplication 初始化收集的 org.springframework.context.ApplicationContextInitializer 所有实现类进行初始化工作
- 利用 org.springframework.boot.context.event.EventPublishingRunListener 向 org.springframework.context.ApplicationListener 发布容器准备好事件
public class SpringApplication {...// 完成属性设置 bean对象创建private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {// 1. 设置容器环境context.setEnvironment(environment);// 2. 执行容器后置处理postProcessApplicationContext(context);// 3. 执行一些初始化器applyInitializers(context); // 4. 向各个监听器发送容器已经准备好的事件listeners.contextPrepared(context);...}
}
- 执行容器后置处理:其实只是往 BeanFactory 添加了基础的转换器
public class SpringApplication {private BeanNameGenerator beanNameGenerator;private ResourceLoader resourceLoader;private boolean addConversionService = true;...protected void postProcessApplicationContext(ConfigurableApplicationContext context) {if (this.beanNameGenerator != null) {context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,this.beanNameGenerator);}if (this.resourceLoader != null) {if (context instanceof GenericApplicationContext) {((GenericApplicationContext) context).setResourceLoader(this.resourceLoader);}if (context instanceof DefaultResourceLoader) {((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader());}}if (this.addConversionService) { // 1. 设置了转换器,例如平时能把整数字符串转换为整形,设置转换器context.getBeanFactory().setConversionService(ApplicationConversionService.getSharedInstance());}}
}
- 执行一些初始化器:就是遍历 org.springframework.context.ApplicationContextInitializer 执行 initialize() 方法
public class SpringApplication {...protected void applyInitializers(ConfigurableApplicationContext context) {for (ApplicationContextInitializer initializer : getInitializers()) {Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),ApplicationContextInitializer.class);Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");initializer.initialize(context);}}
}
- 向各个监听器发送容器已经准备好的事件:就是 org.springframework.boot.context.event.EventPublishingRunListener 向 org.springframework.context.ApplicationListener 发布容器准备好事件
public class SpringApplication {...// 1. 当 ApplicationContext 构建完成时,该方法被调用void contextPrepared(ConfigurableApplicationContext context) {for (SpringApplicationRunListener listener : this.listeners) {listener.contextPrepared(context);}}
}
- 发布完监听之后,从上下文中获取 IOC 工厂,并设置允许 bean 定义被覆盖参数
public class SpringApplication {...// 完成属性设置 bean 对象创建private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {// 设置容器环境context.setEnvironment(environment);// 执行容器后置处理postProcessApplicationContext(context);// 执行一些初始化器applyInitializers(context); // 向各个监听器发送容器已经准备好的事件listeners.contextPrepared(context);if (this.logStartupInfo) {logStartupInfo(context.getParent() == null);logStartupProfileInfo(context);}// 1. 获取 IOC 容器ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();// 将 main() 函数中的 args 参数封装成单例 Bean,注册进容器beanFactory.registerSingleton("springApplicationArguments", applicationArguments);if (printedBanner != null) {// 将 printedBanner 也封装成单例,注册进容器beanFactory.registerSingleton("springBootBanner", printedBanner);}// 2. 设置允许 bean 定义被覆盖参数if (beanFactory instanceof DefaultListableBeanFactory) {((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}...}
}
- 然后加载启动类,并将启动类注入到容器当中,然后发布容器已加载事件
public class SpringApplication {...// 完成属性设置 bean 对象创建private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {// 设置容器环境context.setEnvironment(environment);// 执行容器后置处理postProcessApplicationContext(context);// 执行一些初始化器applyInitializers(context); // 向各个监听器发送容器已经准备好的事件listeners.contextPrepared(context);if (this.logStartupInfo) {logStartupInfo(context.getParent() == null);logStartupProfileInfo(context);}// 获取 IOC 容器ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();// 将 main() 函数中的 args 参数封装成单例 Bean,注册进容器beanFactory.registerSingleton("springApplicationArguments", applicationArguments);if (printedBanner != null) {// 将 printedBanner 也封装成单例,注册进容器beanFactory.registerSingleton("springBootBanner", printedBanner);}// 设置允许 bean 定义被覆盖参数if (beanFactory instanceof DefaultListableBeanFactory) {((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}if (this.lazyInitialization) { // 是否需要进行懒加载,这里不是context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());}// 1. 加载源,这里拿到的是主类,com.lagou.SpringBootMytestApplicationSet<Object> sources = getAllSources();Assert.notEmpty(sources, "Sources must not be empty");// 2. 加载我们的启动类,将启动类注入容器 重点关注load(context, sources.toArray(new Object[0]));// 取出第一个元素,就是主类,要先实例化主类,灌入容器中// 3. 发布容器已加载事件listeners.contextLoaded(context);}
}
- 其中将启动类注入到容器当中是比较关键的一步,首先先把 ApplicationContext 转换成 BeanDefinitionRegistry,然后创建 bean 定义加载器
public class SpringApplication {...protected void load(ApplicationContext context, Object[] sources) {if (logger.isDebugEnabled()) {logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));}// 2. 创建 BeanDefinitionLoaderBeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);...}private BeanDefinitionRegistry getBeanDefinitionRegistry(ApplicationContext context) {// 1. 将 ApplicationContext 转换成 BeanDefinitionRegistryif (context instanceof BeanDefinitionRegistry) {return (BeanDefinitionRegistry) context;}if (context instanceof AbstractApplicationContext) {return (BeanDefinitionRegistry) ((AbstractApplicationContext) context).getBeanFactory();}throw new IllegalStateException("Could not locate BeanDefinitionRegistry");}
}
- 创建 BeanDefinitionLoader 主要是把 BeanDefinitionRegistry 以及主类的 sources 进行赋值初始化
public class SpringApplication {private final Object[] sources;private final AnnotatedBeanDefinitionReader annotatedReader;private final XmlBeanDefinitionReader xmlReader;private BeanDefinitionReader groovyReader;private final ClassPathBeanDefinitionScanner scanner;private ResourceLoader resourceLoader;...protected BeanDefinitionLoader createBeanDefinitionLoader(BeanDefinitionRegistry registry, Object[] sources) {// 1. 创建 bean 定义加载器return new BeanDefinitionLoader(registry, sources);}BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {// 其中,sources 就是主类 com.lagou.SpringBootMytestApplicationAssert.notNull(registry, "Registry must not be null");Assert.notEmpty(sources, "Sources must not be empty");this.sources = sources;// 2. 注解形式的 Bean 定义读取器 比如:@Configuration @Bean @Component @Controller @Service等等this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);// 3. XML 形式的 Bean 定义读取器this.xmlReader = new XmlBeanDefinitionReader(registry);if (isGroovyPresent()) {this.groovyReader = new GroovyBeanDefinitionReader(registry);}// 4. 类路径扫描器this.scanner = new ClassPathBeanDefinitionScanner(registry);// 5. 扫描器添加排除过滤器this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));}
}
- 创建 BeanDefinitionLoader 成功后,就可以开始执行 load(),这里主要是先把主类注册到 IOC 容器中去
public class SpringApplication {private BeanNameGenerator beanNameGenerator;...protected void load(ApplicationContext context, Object[] sources) {if (logger.isDebugEnabled()) {logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));}// 创建 BeanDefinitionLoaderBeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);if (this.beanNameGenerator != null) {loader.setBeanNameGenerator(this.beanNameGenerator);}if (this.resourceLoader != null) {loader.setResourceLoader(this.resourceLoader);}if (this.environment != null) {loader.setEnvironment(this.environment);}// 1. 执行 load()loader.load();}
}
- 其中 load() 通过 AnnotatedBeanDefinitionReader 将主类 source 注册进 beanDefinitionMap 中
class BeanDefinitionLoader {private final AnnotatedBeanDefinitionReader annotatedReader;...int load() {int count = 0;for (Object source : this.sources) {count += load(source);}return count;}// 根据加载不同类型调用不同的方法private int load(Object source) {Assert.notNull(source, "Source must not be null");// 1. 从 Class 加载if (source instanceof Class<?>) {return load((Class<?>) source);}...}private int load(Class<?> source) {// source 就是 class com.lagou.SpringBootMytestApplicationif (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {// Any GroovyLoaders added in beans{} DSL can contribute beans hereGroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);load(loader);}if (isComponent(source)) { // 判断方法有没有标记 Component 注解// 1. 将启动类的 BeanDefinition 注册进 beanDefinitionMapthis.annotatedReader.register(source);return 1;}return 0;}
}
- 调用 register() 方法时,真正会传到 doRegisterBean() 进行执行。首先会把主类转换成 AnnotatedGenericBeanDefinition,然后获取主类的名称,把名称和 AnnotatedGenericBeanDefinition 封装成 BeanDefinitionHolder 后,注册到上下文中
public class AnnotatedBeanDefinitionReader {...public void register(Class<?>... componentClasses) {for (Class<?> componentClass : componentClasses) {registerBean(componentClass);}}public void registerBean(Class<?> beanClass) {doRegisterBean(beanClass, null, null, null, null);}private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,@Nullable BeanDefinitionCustomizer[] customizers) {// 1. 把主类转换成 AnnotatedGenericBeanDefinition,其中 beanClass 为 com.lagou.SpringBootMytestApplicationAnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {return;}abd.setInstanceSupplier(supplier);ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);abd.setScope(scopeMetadata.getScopeName());// 2. 获取类名 springBootMytestApplicationString beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);if (qualifiers != null) {for (Class<? extends Annotation> qualifier : qualifiers) {if (Primary.class == qualifier) {abd.setPrimary(true);}else if (Lazy.class == qualifier) {abd.setLazyInit(true);}else {abd.addQualifier(new AutowireCandidateQualifier(qualifier));}}}if (customizers != null) {for (BeanDefinitionCustomizer customizer : customizers) {customizer.customize(abd);}}// 3. 封装成 BeanDefinitionHolder BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);// 4. 注册到容器中 BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);}
}
- 注册到容器中,简单而言就是调用 BeanDefinitionRegistry 把 BeanDefinitionHolder 的 name 和 AnnotatedGenericBeanDefinition 装配进去
public abstract class BeanDefinitionReaderUtils {...public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {// 1. 获取名称 springBootMytestApplicationString beanName = definitionHolder.getBeanName();// 2. 注册到 IOC 容器中registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());String[] aliases = definitionHolder.getAliases();if (aliases != null) {String[] var4 = aliases;int var5 = aliases.length;for(int var6 = 0; var6 < var5; ++var6) {String alias = var4[var6];registry.registerAlias(beanName, alias);}}}
}
- 最后会把 name 和 AnnotatedGenericBeanDefinition 存入到 beanDefinitionMap 中
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {...public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {Assert.hasText(beanName, "Bean name must not be empty");Assert.notNull(beanDefinition, "BeanDefinition must not be null");// 1. 先校验 beanDefinition 是否合法if (beanDefinition instanceof AbstractBeanDefinition) {try {((AbstractBeanDefinition)beanDefinition).validate();} catch (BeanDefinitionValidationException var8) {throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var8);}}BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);if (existingDefinition != null) {if (!this.isAllowBeanDefinitionOverriding()) {throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);}if (existingDefinition.getRole() < beanDefinition.getRole()) {if (this.logger.isInfoEnabled()) {this.logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");}} else if (!beanDefinition.equals(existingDefinition)) {if (this.logger.isDebugEnabled()) {this.logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");}} else if (this.logger.isTraceEnabled()) {this.logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");}this.beanDefinitionMap.put(beanName, beanDefinition);} else {if (this.hasBeanCreationStarted()) {synchronized(this.beanDefinitionMap) {this.beanDefinitionMap.put(beanName, beanDefinition);List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);updatedDefinitions.addAll(this.beanDefinitionNames);updatedDefinitions.add(beanName);this.beanDefinitionNames = updatedDefinitions;this.removeManualSingletonName(beanName);}} else {// 2. 再把 beanDefinition 放到 beanDefinitionMap 中this.beanDefinitionMap.put(beanName, beanDefinition);this.beanDefinitionNames.add(beanName);this.removeManualSingletonName(beanName);}this.frozenBeanDefinitionNames = null;}if (existingDefinition == null && !this.containsSingleton(beanName)) {if (this.isConfigurationFrozen()) {this.clearByTypeCache();}} else {this.resetBeanDefinition(beanName);}}
}
- 总结

相关文章:
『SpringBoot 源码分析』run() 方法执行流程:(2)刷新应用上下文-准备阶段
『SpringBoot 源码分析』run() 方法执行流程:(2)刷新应用上下文-准备阶段 基于 2.2.9.RELEASE问题:当方法进行了注释标记之后,springboot 又是怎么注入到容器中并创建类呢? 首先创建测试主程序 package …...
WordPress Page Builder KingComposer 2.9.6 Open Redirection
WordPress Page Builder KingComposer 2.9.6 Open Redirection WordPress 插件 KingComposer 版本2.9.6 以及以前版本受到开放重定向漏洞的影响。该漏洞在packetstorm网站披露于2023年7月24日,除了该漏洞,该版本的插件还存在XSS攻击的漏洞风险 图1.来自…...
第五章:中国革命新道路
革命道路的艰难探索 1.国民党在全国统治的建立 南京国民政府的成立国民党政权的性质 2.土地革命战争的兴起 1. 大革命失败后的艰难环境 2. 开启武装反抗国民党统治的斗争: 南昌起义:共产党独立领导的革命战争,创建人民军队和武装夺取政权…...
PMP-沟通管理的重要性
一、什么是项目沟通管理 项目沟通管理包括通过开发工件,以及执行用于有效交换信息的各种活动,来确保项目及其相关方的信息需求得以满足的各个过程。项目沟通管理由两个部分组成:第一部分是制定策略,确保沟通对相关方行之有效&…...
【Sentinel】降级源码:插槽DegradeSlot与断路器的实现
文章目录 1、实现原理2、DegradeSlot类3、CircuitBreaker4、触发断路器 1、实现原理 Sentinel的降级是基于状态机来实现的: 2、DegradeSlot类 熔断降级的逻辑在DegradeSlot类中实现,核心API: Override public void entry(Context context,…...
【Apollo】开启Apollo之旅:让自动驾驶如此简单
前言 Apollo 是百度公司推出的自动驾驶平台。它是一个综合性的自动驾驶解决方案,提供了包括感知、决策、规划和控制等核心功能,以及地图、定位、仿真、数据管理等配套工具。 文章目录 前言Apollo 的发展历程Apollo 8.0新特性软件包管理感知框架工具链小…...
maven搭建spring项目
前提 安装jdk 安装maven 安装eclipse 创建maven项目 搭建spring项目 pom.xml <dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.4.RELEASE</version> </dependency&…...
Java“牵手”阿里巴巴商品详情数据,阿里巴巴商品详情API接口,阿里巴巴国际站API接口申请指南
阿里巴巴平台商品详情接口是开放平台提供的一种API接口,通过调用API接口,开发者可以获取阿里巴巴商品的标题、价格、库存、月销量、总销量、库存、详情描述、图片等详细信息 。 获取商品详情接口API是一种用于获取电商平台上商品详情数据的接口…...
MYSQL调优之思路----sql语句和索引调优
MySQL数据库性能优化包括综合多方面因素,应根据实际的业务情况制定科学、合理的调优方案进行测试调优 文章目录 MySQL性能优化1 优化介绍1.2 优化要考虑的问题2.1 优化可能带来的问题2.2 优化的需求2.3 优化由谁参与2.4 优化的方向2.5 优化的维度 1.2数据库使用优化…...
论文阅读_变分自编码器_VAE
英文名称: Auto-Encoding Variational Bayes 中文名称: 自编码变分贝叶斯 论文地址: http://arxiv.org/abs/1312.6114 时间: 2013 作者: Diederik P. Kingma, 阿姆斯特丹大学 引用量: 24840 1 读后感 VAE 变分自编码(Variational Autoencoder)是一种生…...
springboot整合elasticsearch使用案例
引入依赖 <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId> </dependency> 添加注入 import org.apache.http.HttpHost; import org.elasticsearch.client.Res…...
Unity制作下雨中的地面效果
Unity引擎制作下雨效果 大家好,我是阿赵。 之前介绍了Unity引擎里面通过UV偏移做序列帧动画的做法,这里再介绍一个进阶的用法,模拟地面下雨的雨点效果。 一、原理 最基本的原理,还是基于这个序列帧动画的做法。不过这里做一点…...
windows从0搭建python3开发环境与开发工具
文章目录 一、python3下载安装1、下载2、安装3、测试 二、安装VS Code1、安装2、安装python插件3、测试 三、pip命令的使用1、基本命令2、修改pip下载源 一、python3下载安装 1、下载 打开 WEB 浏览器访问 https://www.python.org/downloads/windows/ ,一般就下载…...
centos中得一些命令 记录
redis命令 链接redis数据库的命令 redis-cli如果 Redis 服务器在不同的主机或端口上运行,你需要提供相应的主机和端口信息。例如: redis-cli -h <hostname> -p <port>连接成功后,你将看到一个类似于以下的提示符,表…...
Python实现Word、Excel、PPT批量转为PDF
今天看见了一个有意思的脚本Python批量实现Word、EXCLE、PPT转PDF文件。 因为我平时word用的比较的多,所以深有体会,具体怎么实现的我们就不讨论了,因为这个去学了也没什么提升,不然也不会当作脚本了。这里我将其放入了pyzjr库中…...
LLM大模型推理加速 vLLM
参考: https://github.com/vllm-project/vllm https://zhuanlan.zhihu.com/p/645732302 https://vllm.readthedocs.io/en/latest/getting_started/quickstart.html ##文档 加速原理: PagedAttention,主要是利用kv缓存 使用: #…...
Python|小游戏之猫捉老鼠!!!
最近闲(mang)来(dao)无(fei)事(qi),喜欢研究一些小游戏,本篇文章我主要介绍使用 turtle 写的一个很简单的猫捉老鼠的小游戏,主要是通过鼠标控制老鼠(Tom)的移动,躲避通过电脑控制的猫(Jerry)的追捕。 游戏主体思考逻辑࿱…...
万里路,咫尺间:汽车与芯片的智能之遇
目前阶段,汽车产业有两个最闪耀的关键词,就是智能与低碳。 在践行双碳目标与产业智能化的大背景下,汽车已经成为了能源技术、交通技术、先进制造以及通信、数字化、智能化技术的融合体。汽车的产品形态与产业生态都在发生着前所未有的巨大变革…...
Ubuntu22.04.1上 mosquitto安装及mosquitto-auth-plug 认证插件配置
Ubuntu22.04.1上 mosquitto安装及mosquitto-auth-plug 认证插件配置 1、先上效果,可以根据mysql中mosquitto数据库的不同users角色登陆mosquitto: SELECT * FROM mosquitto.users; id,username,pw,super 1,jjolie,PBKDF2$sha256$901$yZnELWKK4NnaNNJl…...
CCKS2023:基于企业数仓和大语言模型构建面向场景的智能应用
8月24日-27日,第十七届全国知识图谱与语义计算大会(CCKS 2023)在沈阳召开。大会以“知识图谱赋能通用AI”为主题,探讨知识图谱对通用AI技术的支撑能力,探索知识图谱在跨平台、跨领域等AI任务中的作用和应用途径。 作为…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
C# winform教程(二)----checkbox
一、作用 提供一个用户选择或者不选的状态,这是一个可以多选的控件。 二、属性 其实功能大差不差,除了特殊的几个外,与button基本相同,所有说几个独有的 checkbox属性 名称内容含义appearance控件外观可以变成按钮形状checkali…...
TCP/IP 网络编程 | 服务端 客户端的封装
设计模式 文章目录 设计模式一、socket.h 接口(interface)二、socket.cpp 实现(implementation)三、server.cpp 使用封装(main 函数)四、client.cpp 使用封装(main 函数)五、退出方法…...
高效的后台管理系统——可进行二次开发
随着互联网技术的迅猛发展,企业的数字化管理变得愈加重要。后台管理系统作为数据存储与业务管理的核心,成为了现代企业不可或缺的一部分。今天我们要介绍的是一款名为 若依后台管理框架 的系统,它不仅支持跨平台应用,还能提供丰富…...
k8s从入门到放弃之Pod的容器探针检测
k8s从入门到放弃之Pod的容器探针检测 在Kubernetes(简称K8s)中,容器探测是指kubelet对容器执行定期诊断的过程,以确保容器中的应用程序处于预期的状态。这些探测是保障应用健康和高可用性的重要机制。Kubernetes提供了两种种类型…...
02-性能方案设计
需求分析与测试设计 根据具体的性能测试需求,确定测试类型,以及压测的模块(web/mysql/redis/系统整体)前期要与相关人员充分沟通,初步确定压测方案及具体的性能指标QA完成性能测试设计后,需产出测试方案文档发送邮件到项目组&…...
