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

源码分析spring如和对@Component注解进行BeanDefinition注册的

Spring ioc主要职责为依赖进行处理(依赖注入、依赖查找)、容器以及托管的(java bean、资源配置、事件)资源声明周期管理;在ioc容器启动对元信息进行读取(比如xml bean注解等)、事件管理、国际化等处理;首先spring中定义的元信息为BeanDefinition,Spring BeanDefinition解析与注册不同的资源有不同的实现,

  • XML资源 XmlBeanDefinitionReader
  • Properties资源 PropertiesBeanDefinitionReader
  • JAVA注解 AnnotationBeanDefinitionReader

在实际工作中,注解用的偏多,接下来使用AnnotationConfigApplicationContext来实例化我们spring ioc容器。并进行源码分析。


@Component
public class Demo {public static void main(String[] args) {AnnotationConfigApplicationContext annotationConfigApplicationContext =new AnnotationConfigApplicationContext();annotationConfigApplicationContext.register(Demo.class);annotationConfigApplicationContext.refresh();Person person = annotationConfigApplicationContext.getBean(Person.class);System.out.println(person);annotationConfigApplicationContext.close();}@Componentpublic static class Test {@Beanpublic Person createUser() {Person person = new Person();person.setName(UUID.randomUUID().toString());return person;}}public static class Person {private String name;// toString get set 省略}
}

输出结果:

Person{name='36874349-794b-4adf-b877-2666f54b8287'}

我们仅仅注册了Demo类,AnnotationConfigApplicationContext如何进行@Bean和@Component注解进行查找呢?

前面我们提到了注解类用到AnnotationBeanDefinitionReader类进行BeanDefinition的解析与注册,在我们初始化代码的是也可以看到创建了AnnotationBeanDefinitionReader对象,并在AnnotationBeanDefinitionReader构建方法中调用AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);进行注解BeanDefinition的默认后置处理。


...省略
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
...省略

ConfigurationClassPostProcessor.class类为重点关注类

然后调用注册我们的Demo.clss 解析我们该类,生成
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
最后通过调用BeanDefinitionReaderUtils#registerBeanDefinition()方法进行注册BeanDefinition。

Spring context#refresh()方法


public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");// Prepare this context for refreshing.//准备刷新上下文prepareRefresh();// Tell the subclass to refresh the internal bean factory.//告诉子类刷新内部bean工厂ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.//将该BeanFactory应用于上下文,默认BeanFactory实现为DefaultListableBeanFactory。查看源码得知道context也是基础BeanFactory,但进行依赖查找的时候会调用getBeanFactory().getBean(xx)进行处理,可理解为context对象与BeanFactory是一种特殊的组合,也可以理解为context对象是对BeanFactory的一种封装。prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.//允许在上下文子类中对bean工厂进行后置处理postProcessBeanFactory(beanFactory);StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");// Invoke factory processors registered as beans in the context.// 调用上下文中注册为bean的工厂处理器 完成对BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor的后置处理器调用invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);//注册拦截器bean创建的bean处理器beanPostProcess.end();// Initialize message source for this context.//初始化此上下文的消息源,列如如国际化initMessageSource();// Initialize event multicaster for this context.//为此上下文初始化事件多播initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.// 初始化特定上下文子类中的其他特殊beanonRefresh();// Check for listener beans and register them.//检查监听器bean并注册registerListeners();// Instantiate all remaining (non-lazy-init) singletons.//实例化非懒加载的单例 实例化beanfinishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.//完成事件发布finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();contextRefresh.end();}}}   

先入为主,我们看到invokeBeanFactoryPostProcessors 方法为完成对BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor的后置处理器调用,那我们直接跟踪源码
进入到
PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(beanfactory,branfactoryPostProcessors)方法。跟踪代码找相应的的bean 元信息注册的处理器。

特别注意,改方法可以分为两部分进行理解,第一次部分是对BeanDefinitionRegistryPostProcessor进行处理,第二部分是对BeanFactoryPostProcessor进行处理

首先按照类型BeanDefinitionRegistryPostProcessor.class查找后置处理器的名字,在我们初始spring上线下文中,注入了ConfigurationClassPostProcessor类,并行该类实现了BeanDefinitionRegistryPostProcessor.class。如下uml图
uml

ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry(registry) BeanDefinition解析与注册

顺利的拿到了ConfigurationClassPostProcessor类,接下来进行排序,执行PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors()方法。

  /*** Invoke the given BeanDefinitionRegistryPostProcessor beans.*/
private static void invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process").tag("postProcessor", postProcessor::toString);postProcessor.postProcessBeanDefinitionRegistry(registry);postProcessBeanDefRegistry.end();}
}

此时对应的BeanDefinitionRegistryPostProcessor类型的processor是ConfigurationClassPostProcessor,调用ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry(registry)


/*** Derive further bean definitions from the configuration classes in the registry.*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {int registryId = System.identityHashCode(registry);if (this.registriesPostProcessed.contains(registryId)) {throw new IllegalStateException("postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);}if (this.factoriesPostProcessed.contains(registryId)) {throw new IllegalStateException("postProcessBeanFactory already called on this post-processor against " + registry);}this.registriesPostProcessed.add(registryId);processConfigBeanDefinitions(registry);
}

接下来我们进入processConfigBeanDefinitions(registry)方法


/*** Build and validate a configuration model based on the registry of* {@link Configuration} classes.*/
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {List<BeanDefinitionHolder> configCandidates = new ArrayList<>();String[] candidateNames = registry.getBeanDefinitionNames();//  循环注入的BeanDefinition,前面我们demo已经注册了Demo类的 BeanDefinition。for (String beanName : candidateNames) {BeanDefinition beanDef = registry.getBeanDefinition(beanName);if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {if (logger.isDebugEnabled()) {logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);}}//是否是配置类,是否包涵Component、ComponentScan、Import、ImportResource注解,以及最后检查是否带有@Bean的方法。最后打上标记else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));}}
...省略do {StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");//进行配置类扫描,扫描成员类以及带有ComponentScans.class、PropertySources.class,ComponentScans.class、 ImportResource.classparser.parse(candidates);parser.validate();Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());configClasses.removeAll(alreadyParsed);// Read the model and create bean definitions based on its contentif (this.reader == null) {this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment,this.importBeanNameGenerator, parser.getImportRegistry());}//开始注册我们解析到的配置类,读取配置类,生成BeanDefinition,并注入到当前容器中this.reader.loadBeanDefinitions(configClasses);alreadyParsed.addAll(configClasses);processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();candidates.clear();if (registry.getBeanDefinitionCount() > candidateNames.length) {String[] newCandidateNames = registry.getBeanDefinitionNames();Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));Set<String> alreadyParsedClasses = new HashSet<>();for (ConfigurationClass configurationClass : alreadyParsed) {alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());}//对比新生成的BeanDefinition,执行ConfigurationClassUtils.checkConfigurationClassCandidate。进行标记for (String candidateName : newCandidateNames) {if (!oldCandidateNames.contains(candidateName)) {BeanDefinition bd = registry.getBeanDefinition(candidateName);if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&!alreadyParsedClasses.contains(bd.getBeanClassName())) {candidates.add(new BeanDefinitionHolder(bd, candidateName));}}}candidateNames = newCandidateNames;}}...省略

ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)


Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
else if (config != null || isConfigurationCandidate(metadata)) {beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {return false;
}....public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {// Do not consider an interface or an annotation...if (metadata.isInterface()) {return false;}// Any of the typical annotations found?//是否匹配Component.class、ComponentScan.class、Import.class、ImportResource.class注解for (String indicator : candidateIndicators) {if (metadata.isAnnotated(indicator)) {return true;}}// Finally, let's look for @Bean methods...//查找是否含有注解bean的方法。return hasBeanMethods(metadata);
}

该方法解析注册BeanDefinition中是否包涵@Configuration注解以及是否包含配置的选项,并进行如果BeanDefinition元信息中包涵Configuration.class注解,并且proxyBeanMethods配置不为false,设置BeanDefinition的configurationClass属性为full,否则判断是否包涵配置候选bean 将该BeanDefinition的configurationClass属性为lite。

该方法是用来判断一个是否是一个配置类,并为BeanDefinition设置属性为lite或者full。如果加了@Configuration,并且对应@Configuration注解的proxyBeanMethods配置不为false那么对应的BeanDefinition为full,如果加了@Bean,@Component,@ComponentScan,@Import,@ImportResource这些注解和@Configuration的proxyBeanMethods配置为false,则为lite。lite和full均表示这个BeanDefinition对应的类是一个配置类。

初次标记完后,然后继续跟踪到配置类的解析,通过ConfigurationClassParser.parse(candidates)解析每一个配置类。对注入不同的BeanDefinition分别处理,我们优先看@Component注解类型的AnnotatedBeanDefinition,
开始对我们注册的BeanDefinition进行元信息进行解析ConfigurationClassParser#parse最终到processConfigurationClass#processConfigurationClass(configClass,filter)


protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {return;}ConfigurationClass existingClass = this.configurationClasses.get(configClass);if (existingClass != null) {if (configClass.isImported()) {if (existingClass.isImported()) {existingClass.mergeImportedBy(configClass);}// Otherwise ignore new imported config class; existing non-imported class overrides it.return;}else {// Explicit bean definition found, probably replacing an import.// Let's remove the old one and go with the new one.this.configurationClasses.remove(configClass);this.knownSuperclasses.values().removeIf(configClass::equals);}}// Recursively process the configuration class and its superclass hierarchy.SourceClass sourceClass = asSourceClass(configClass, filter);do {//开始解析配置类 读取注解、成员和方法,应用处理并构建完整的配置类,新解析到的配置类 进行递归解析。sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);}while (sourceClass != null);this.configurationClasses.put(configClass, configClass);}

来到我们解析成员类


/*** Register member (nested) classes that happen to be configuration classes themselves.*/private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass,Predicate<String> filter) throws IOException {Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();if (!memberClasses.isEmpty()) {List<SourceClass> candidates = new ArrayList<>(memberClasses.size());for (SourceClass memberClass : memberClasses) {//排除非配置类,和防止重复引用的类if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) &&!memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {candidates.add(memberClass);}}OrderComparator.sort(candidates);for (SourceClass candidate : candidates) {if (this.importStack.contains(configClass)) {this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));}else {this.importStack.push(configClass);try {//将SourceClass转换为ConfigurationClass类,此处标记该成员类的所属类processConfigurationClass(candidatenfigClass(configClass), filter);}finally {this.importStack.pop();}}}}}

跟踪到ConfigurationClassParser#doProcessConfigurationClass(configClass,sourceClass, filter)方法,首先是判断是否包涵Component注解,然后开始解析成员类。然后继续递处理配置类。

回到processConfigBeanDefinitions方法中,调用ConfigurationClassBeanDefinitionReader#loadBeanDefinitions(configClasses);加载解析注册BeanDefinition

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();for (ConfigurationClass configClass : configurationModel) {loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);}}/*** Read a particular {@link ConfigurationClass}, registering bean definitions* for the class itself and all of its {@link Bean} methods.*/private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {if (trackedConditionEvaluator.shouldSkip(configClass)) {String beanName = configClass.getBeanName();if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {this.registry.removeBeanDefinition(beanName);}this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());return;}//解析到的类是否是导入进来的,所依赖进来的,示例代码中Test配置类是Demo的成员类if (configClass.isImported()) {//注册BeanDefinitionregisterBeanDefinitionForImportedConfigurationClass(configClass);}for (BeanMethod beanMethod : configClass.getBeanMethods()) {//加载带有@Bean方法的注解方法,并注册BeanDefinitionloadBeanDefinitionsForBeanMethod(beanMethod);}// 判断是否被导入进来的资源配置groovy以及xmlloadBeanDefinitionsFromImportedResources(configClass.getImportedResources());//(方便扩展)取出实现了ImportBeanDefinitionRegistrar接口的类,执行其registerBeanDefinitions方法。读取自定义实现的Registrar 注入到容器中。可以参考dubbo的DubboComponentScanRegistrar 实现loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());}

回到processConfigBeanDefinitions方法中,最后将新的注册的BeanDefinition进行属性标记。

最终完成了我们BeanDefinition解析与注册。

相关文章:

源码分析spring如和对@Component注解进行BeanDefinition注册的

Spring ioc主要职责为依赖进行处理&#xff08;依赖注入、依赖查找&#xff09;、容器以及托管的(java bean、资源配置、事件)资源声明周期管理&#xff1b;在ioc容器启动对元信息进行读取&#xff08;比如xml bean注解等&#xff09;、事件管理、国际化等处理&#xff1b;首先…...

C语言--字符串函数1

目录前言strlenstrlen的模拟实现strcpystrcatstrcat的模拟实现strcmpstrcmp的模拟实现strncpystrncatstrncmpstrstrstrchr和strrchrstrstr的模拟实现前言 本章我们将重点介绍处理字符和字符串的库函数的使用和注意事项。 strlen 我们先来看一个我们最熟悉的求字符串长度的库…...

Webstorm使用、nginx启动、FinalShell使用

文章目录 主题设置FinalShellFinalShell nginx 启动历史命令Nginx页面发布配置Webstorm的一些常用快捷键代码生成字体大小修改Webstorm - gitCode 代码拉取webstorm 汉化webstorm导致CPU占用率高方法一 【忽略node_modules】方法二 【设置 - 代码编辑 - 快速预览文档 - 关闭】主…...

源码分析Spring @Configuration注解如何巧夺天空,偷梁换柱。

前言 回想起五年前的一次面试&#xff0c;面试官问Configuration注解和Component注解有什么区别&#xff1f;记得当时的回答是&#xff1a; 相同点&#xff1a;Configuration注解继承于Component注解&#xff0c;都可以用来通过ClassPathBeanDefinitionScanner装载Spring bean…...

vector的使用及模拟实现

目录 一.vector的介绍及使用 1.vector的介绍 2.vector的使用 1.vector的定义 2.vector iterator的使用 3. vector 空间增长问题 4.vector 增删查改 3.vector 迭代器失效问题&#xff08;重点&#xff09; 1. 会引起其底层空间改变的操作 2.指定位置元素的删除操作--erase 3. Li…...

“华为杯”研究生数学建模竞赛2007年-【华为杯】A题:基于自助法和核密度估计的膳食暴露评估模型(附获奖论文)

赛题描述 我国是一个拥有13亿人口的发展中国家,每天都在消费大量的各种食品,这批食品是由成千上万的食品加工厂、不可计数的小作坊、几亿农民生产出来的,并且经过较多的中间环节和长途运输后才为广大群众所消费,加之近年来我国经济发展迅速而环境治理没有能够完全跟上,以…...

刷题(第三周)

目录 [CISCN2021 Quals]upload [羊城杯 2020]EasySer [网鼎杯 2020 青龙组]notes [SWPU2019]Web4 [Black Watch 入群题]Web [HFCTF2020]BabyUpload [CISCN2021 Quals]upload 打开界面以后&#xff0c;发现直接给出了源码 <?php if (!isset($_GET["ctf"]))…...

新C++(14):移动语义与右值引用

当你在学习语言的时候&#xff0c;是否经常听到过一种说法,""左边的叫做左值&#xff0c;""右边的叫做右值。这句话对吗&#xff1f;从某种意义上来说&#xff0c;这句话只是说对了一部分。---前言一、什么是左右值?通常认为:左值是一个表示数据的表达式(…...

TCP相关概念

目录 一.滑动窗口 1.1概念 1.2滑动窗口存在的意义 1.3 滑动窗口的大小变化 1.4丢包问题 二.拥塞控制 三.延迟应答 四.捎带应答 五.面向字节流 六.粘包问题 七.TIME_WAIT状态 八.listen第2个参数 九.TCP总结 一.滑动窗口 1.1概念 概念&#xff1a;双方在进行通信时&a…...

MySQL锁篇

MySQL锁篇 一、一条update语句 我们的故事继续发展&#xff0c;我们还是使用t这个表&#xff1a; CREATE TABLE t (id INT PRIMARY KEY,c VARCHAR(100) ) EngineInnoDB CHARSETutf8;现在表里的数据就是这样的&#xff1a; mysql> SELECT * FROM t; —------- | id | c | —…...

SWF (Simple Workflow Service)简介

Amazon Simple Workflow Service (Amazon SWF) 提供了给应用程序异步、分布式处理的流程工具。 SWF可以用在媒体处理、网站应用程序后端、商业流程、数据分析和一系列定义好的任务上。 举个例子&#xff0c;下图表明了一个电商网站的工作流程&#xff0c;其中涉及了程序执行的…...

java(Class 常用方法 获取Class对象六种方式 动态和静态加载 类加载流程)

ClassClass常用方法获取Class对象六种方式哪些类型有Class对象动态和静态加载类加载流程加载阶段连接阶段连接阶段-验证连接阶段-准备连接阶段-解析初始化阶段获取类结构信息Class常用方法 第一步&#xff1a;创建一个实体类 public class Car {public String brand "宝…...

【数据结构】线性表和顺序表

Yan-英杰的主页 悟已往之不谏 知来者之可追 目录 1.线性表 2.顺序表 2.1 静态顺序表 2.2 动态顺序表 2.3移除元素 1.线性表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线…...

Ubuntu数据库安装(mysql)

##1.下载mysql-apt-config_0.8.22-1_all.deb并且安装 wget https://dev.mysql.com/get/mysql-apt-config_0.8.22-1_all.deb sudo dpkg -i mysql-apt-config_0.8.22-1_all.deb##2.更新apt-updata sudo apt update##3.如果出现如下图情况执行以下命令 [外链图片转存失败,源站可…...

MyBatis-Plus的入门学习

MyBatis-Plus入门学习简介特性快速开始MyBatis-Plus的注解详解Tableld主键生成策略1、数据库自动增长 AUTO2、UUID3、Redis生成id4、MP主键自动生成TableNameTableField自动填充测试方法&#xff1a;update乐观锁select查所有根据id查多个id批量查询简单条件查询&#xff08;通…...

华为OD机试题 - 内存池(JavaScript)

更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 华为OD机试题 最近更新的博客使用说明本篇题解:内存池题目输入输出示例一输入输出说明Code解题思路版权说明华为…...

数据库索引原理

数据库索引的作用是做数据的快速检索&#xff0c;而快速检索实现的本质是数据结构。像二叉树、红黑树、AVL树、B树、B树、哈希等数据结构都可以实现索引&#xff0c;但其中B树效率最高。MySQL数据库索引使用的是B树。二叉树&#xff1a;二叉树中&#xff0c;左子树比根节点小&a…...

字符函数和字符串函数详解(1)

目录前言strlen函数strlensizeofstrcpy函数strcat函数strcmp函数总结前言 最近要调整状态&#xff0c;写的文章质量不佳让大家失望&#xff0c;我现在也在反思我在做什么&#xff0c;我会什么&#xff0c;我学了什么。等我想明白的那天&#xff0c;我一定能跟大家顶峰相见的&a…...

【数据分析:工具篇】NumPy(1)NumPy介绍

【数据分析&#xff1a;工具篇】NumPy&#xff08;1&#xff09;NumPy介绍NumPy介绍NumPy的特点数组的基本操作创建数组索引和切片数组运算NumPy介绍 NumPy&#xff08;Numerical Python&#xff09;是Python的一个开源的科学计算库&#xff0c;它主要用于处理大规模的多维数组…...

mysql时区问题

设置mysql容器时间与服务器时间一致 问题背景&#xff1a; 今天测试发现一个问题&#xff0c;时间不一致&#xff0c;当工单入库时&#xff0c;其创建时间和更新时间应该是一样的&#xff0c;即使不一样最多只会错几秒的时间&#xff1b;实际上两个时间相差的大概8小时&#…...

磨金石教育摄影技能干货分享|高邮湖上观花海

江苏高邮&#xff0c;说到这里所有人能想到的&#xff0c;就是那烟波浩渺的高邮湖。高邮在旅游方面并不出名&#xff0c;但是这里的自然人文景观绝对不输于其他地方。高邮不止有浩瀚的湖泊&#xff0c;春天的油菜花海同样壮观。春日的午后&#xff0c;与家人相约游玩&#xff0…...

mysql navicat忘记密码

mysql忘记密码是常用的事情&#xff0c;那么如何解决它呢&#xff1f;1、首先将MySQL的服务关闭&#xff0c;两种方法&#xff1a;&#xff08;1&#xff09;打开命令行cmd输入net stop mysql命令即可关闭MySQL服务。&#xff08;2&#xff09;打开任务管理器&#xff0c;找到服…...

Git的下载、安装、配置、使用、卸载

前言 我是跟着狂神老师学的。该博客仅用于笔记所用。 下面是老师的B站和笔记 B站&#xff1a;https://www.bilibili.com/video/BV1FE411P7B3?p1&vd_source9266cf72b1f398b63abe0aefe358d7d6 笔记&#xff1a;https://mp.weixin.qq.com/s/Bf7uVhGiu47uOELjmC5uXQ 一、准备工…...

【博客631】监控网卡与进程网络IO使用情况

监控进程的网络IO使用情况 1、vnstat 由于 vnstat 依赖于内核提供的信息&#xff0c;因此执行以下命令来验证内核是否提供了 vnStat 所期望的所有信息&#xff1a; # vnstat --testkernel This test will take about 60 seconds. Everything is ok.不带任何参数的 vnstat 将…...

【Leetcode】【简单】35. 搜索插入位置

给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 示例 1: 输入: nums [1,3,5,6], target 5 输出: 2 示例 2: 输入:…...

sql面试题

mysql优化 优化准则&#xff1a; 建表时&#xff1a;合理选择字段的类型&#xff0c;单表字段数量 sql查询尽量单表操作&#xff0c;避免复杂操作&#xff0c;复杂的多表通过java代码实现 构建复合索引优化&#xff0c;索引尽量可以覆盖主要业务查询 sql避免索引失效 避免大…...

SQL 进阶刷题笔记

SQL 进阶刷题笔记 一、MySQL 进阶 这里主要是 MySQL 刷题相关笔记&#xff0c;方便后面温习和查阅&#xff0c;希望可以帮到大家&#xff01;&#xff01;&#xff01; 题1 请计算每张SQL类别试卷发布后&#xff0c;当天5级以上的用户作答的人数uv和平均分avg_score&#xff0…...

[网鼎杯 2020 朱雀组]Think Java

SqlDict.java ,其中sql语句处存在sql注入漏洞 package .sqldict;import cn.abc.core.sqldict.Row; import cn.abc.core.sqldict.Table; import java...

AIR32F103(十) 在无系统环境和FreeRTOS环境集成LVGL

目录 AIR32F103(一) 合宙AIR32F103CBT6开发板上手报告AIR32F103(二) Linux环境和LibOpenCM3项目模板AIR32F103(三) Linux环境基于标准外设库的项目模板AIR32F103(四) 27倍频216MHz,CoreMark跑分测试AIR32F103(五) FreeRTOSv202112核心库的集成和示例代码AIR32F103(六) ADC,I2S…...

SpringBoot接口 - 如何统一异常处理

SpringBoot接口如何对异常进行统一封装&#xff0c;并统一返回呢&#xff1f;以上文的参数校验为例&#xff0c;如何优雅的将参数校验的错误信息统一处理并封装返回呢&#xff1f;为什么要优雅的处理异常如果我们不统一的处理异常&#xff0c;经常会在controller层有大量的异常…...

哪个网站做试卷吧有答案/seo排名赚app最新版本

进入about:config.修改dom.ipc.plugins.enabled.npctrl.dll&#xff0c;把它由true改成false重启Firefox就可以调试了。转载于:https://www.cnblogs.com/lfzwenzhu/archive/2011/02/23/1962198.html...

wordpress 自定义逻辑/济南百度竞价开户

在windows下可以很方便的查看磁盘空间的。但是到了Linux查看磁盘空间,你可能就有点摸不着头脑了&#xff0c;呵呵。不要急&#xff0c;我这就要给你解决这个问题。Df命令是Linux查看磁盘空间系统以磁盘分区为单位查看文件系统&#xff0c;可以加上参数查看磁盘剩余空间信息&…...

网站关键词作用/湖北百度推广公司

开发四年只会写业务代码&#xff0c;分布式高并发都不会还做程序员&#xff1f; 微软在去年11月正式推出了微软 Windows 10 1809 版本&#xff0c;这个十月更新版本的发布过程可谓是曲折坎坷。发布后撤回、延期&#xff0c;各种问题的发生大大降低了用户升级的积极性。 所以很…...

html5网站是用什么软件做的/地推一手项目平台

shared_ptr&#xff1a;资源管理利器 如果你还在使用传统的C&#xff0c;那么可以肯定堆内存的管理让你头痛过&#xff01;在传统的C领域&#xff0c;堆内存管理上我们能借用的现成工具就只有auto_ptr。但是很不幸用auto_ptr管理堆内存简直就是个错误。auto_ptr的问题可以归结为…...

有什么网络项目可以做的/四川seo

最近要做一个java web项目&#xff0c;因为页面不是很多&#xff0c;所以就没有前后端分离&#xff0c;前后端写在一起&#xff0c;这时候就用到thymeleaf了&#xff0c;以下是不动脑式的傻瓜教程。。。。。一&#xff1a;创建spring boot的web项目&#xff0c;过程略&#xff…...

那种非法网站怎么做的/南宁百度关键词推广

Pentium 4&#xff08;P4&#xff09; 第一款P4处理器是Intel在2000年11月21日发布的P4 1.5GHz处理器&#xff0c;从那以后到现在近四年的时间里&#xff0c;P4处理器随着规格的不断变化已经发展成了具有近10种不同规格的处理器家族。在这里面&#xff0c;“P4 XXGHz”是最简单…...