Spring系列之BeanFactory扩展(BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor)

2023-11-18

先来看几个问题

  1. BeanFactoryPostProcessor是做什么的?

  2. BeanDefinitionRegistryPostProcessor是干什么的?

  3. BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor有什么区别?

  4. 这几个接口的执行顺序是什么样的?

Spring容器中主要的4个阶段

  • 阶段1:Bean注册阶段,此阶段会完成所有bean的注册

  • 阶段2:BeanFactory后置处理阶段

  • 阶段3:注册BeanPostProcessor

  • 阶段4:bean创建阶段,此阶段完成所有单例bean的注册和装载操作,这个阶段不是我们本文关注的重点,有兴趣的,可以去看之前的文章中有详细介绍:Bean生命周期详解

本文介绍的2个接口主要和前2个阶段有关系,下面我们主要来看前2个阶段。

阶段1:Bean注册阶段

概述

spring中所有bean的注册都会在此阶段完成,按照规范,所有bean的注册必须在此阶段进行,其他阶段不要再进行bean的注册。

这个阶段spring为我们提供1个接口:BeanDefinitionRegistryPostProcessor,spring容器在这个阶段中会获取容器中所有类型为BeanDefinitionRegistryPostProcessor的bean,然后会调用他们的postProcessBeanDefinitionRegistry方法,源码如下,方法参数类型是BeanDefinitionRegistry,这个类型大家都比较熟悉,即bean定义注册器,内部提供了一些方法可以用来向容器中注册bean。

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}

这个接口还继承了BeanFactoryPostProcessor接口,这个大家先不用关心,一会阶段2中会介绍。

当容器中有多个BeanDefinitionRegistryPostProcessor的时候,可以通过下面任意一种方式来指定顺序

  1. 实现org.springframework.core.PriorityOrdered接口

  2. 实现org.springframework.core.Ordered接口

执行顺序:

PriorityOrdered.getOrder() asc,Ordered.getOrder() asc

下面通过案例来感受一下效果。

案例1:简单实用

此案例演示BeanDefinitionRegistryPostProcessor的简单使用

自定义一个BeanDefinitionRegistryPostProcessor

下面我们定义了一个类,需要实现BeanDefinitionRegistryPostProcessor接口,然后会让我们实现2个方法,大家重点关注postProcessBeanDefinitionRegistry这个方法,另外一个方法来自于BeanFactoryPostProcessor,一会我们后面在介绍这个方法,在postProcessBeanDefinitionRegistry方法中,我们定义了一个bean,然后通过registry将其注册到容器了,代码很简单

package com.javacode2018.lesson003.demo3.test0;

@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        //定义一个字符串类型的bean
        AbstractBeanDefinition userNameBdf = BeanDefinitionBuilder.
                genericBeanDefinition(String.class).
                addConstructorArgValue("路人").
                getBeanDefinition();
        //将userNameBdf注册到spring容器中
        registry.registerBeanDefinition("userName", userNameBdf);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }
}

同包中来个配置类

package com.javacode2018.lesson003.demo3.test0;

import org.springframework.context.annotation.ComponentScan;

@ComponentScan
public class MainConfig0 {
}

测试用例

package com.javacode2018.lesson003.demo3;

import com.javacode2018.lesson003.demo3.test0.MainConfig0;
import com.javacode2018.lesson003.demo3.test1.MainConfig1;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class BeanDefinitionRegistryPostProcessorTest {
    @Test
    public void test0() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(MainConfig0.class);
        context.refresh();
        System.out.println(context.getBean("userName"));
    }
}

运行输出

路人

案例2:多个指定顺序

下面我们定义2个BeanDefinitionRegistryPostProcessor,都实现Ordered接口,第一个order的值为2,第二个order的值为1,我们来看一下具体执行的顺序。

第一个

package com.javacode2018.lesson003.demo3.test1;

@Component
public class BeanDefinitionRegistryPostProcessor1 implements BeanDefinitionRegistryPostProcessor, Ordered {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println(String.format("BeanDefinitionRegistryPostProcessor1{order=%d},注册name bean,", this.getOrder()));
        //定义一个bean
        AbstractBeanDefinition nameBdf = BeanDefinitionBuilder.
                genericBeanDefinition(String.class).
                addConstructorArgValue("路人甲java").
                getBeanDefinition();
        //将定义的bean注册到容器
        registry.registerBeanDefinition("name", nameBdf);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }

    @Override
    public int getOrder() {
        return 2;
    }
}

第二个

package com.javacode2018.lesson003.demo3.test1;

@Component
public class BeanDefinitionRegistryPostProcessor2 implements BeanDefinitionRegistryPostProcessor, Ordered {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println(String.format("BeanDefinitionRegistryPostProcessor2{order=%d},注册car bean,", this.getOrder()));
        //定义一个bean
        AbstractBeanDefinition nameBdf = BeanDefinitionBuilder.
                genericBeanDefinition(String.class).
                addConstructorArgValue("保时捷").
                getBeanDefinition();
        //将定义的bean注册到容器
        registry.registerBeanDefinition("car", nameBdf);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }

    @Override
    public int getOrder() {
        return 1;
    }
}

上面2个类中的postProcessBeanDefinitionRegistry方法第一行都有输出,一个可以通过运行结果看到执行的顺序。

同包中添加配置类

package com.javacode2018.lesson003.demo3.test1;

import org.springframework.context.annotation.ComponentScan;

@ComponentScan
public class MainConfig1 {
}

测试案例

@Test
public void test1() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.register(MainConfig1.class);
    context.refresh();
    context.getBeansOfType(String.class).forEach((beanName, bean) -> {
        System.out.println(String.format("%s->%s", beanName, bean));
    });
}

运行输出

BeanDefinitionRegistryPostProcessor2{order=1},注册car bean,
BeanDefinitionRegistryPostProcessor1{order=2},注册name bean,
car->保时捷
name->路人甲java

小结

BeanDefinitionRegistryPostProcessor有个非常重要的实现类:

org.springframework.context.annotation.ConfigurationClassPostProcessor

这个类可能有些人不熟悉,下面这些注解大家应该比较熟悉吧,这些注解都是在上面这个类中实现的,通过这些注解来实现bean的批量注册

@Configuration
@ComponentScan
@Import
@ImportResource
@PropertySource

有兴趣的朋友可以去看一下ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry研究一下上面这些注解的解析过程,可以学到很多东西。

阶段2:BeanFactory后置处理阶段

概述

到这个阶段的时候,spring容器已经完成了所有bean的注册,这个阶段中你可以对BeanFactory中的一些信息进行修改,比如修改阶段1中一些bean的定义信息,修改BeanFactory的一些配置等等,此阶段spring也提供了一个接口来进行扩展:BeanFactoryPostProcessor,简称bfpp,接口中有个方法postProcessBeanFactory,spring会获取容器中所有BeanFactoryPostProcessor类型的bean,然后调用他们的postProcessBeanFactory,来看一下这个接口的源码:

@FunctionalInterface
public interface BeanFactoryPostProcessor {

    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

当容器中有多个BeanFactoryPostProcessor的时候,可以通过下面任意一种方式来指定顺序

  1. 实现org.springframework.core.PriorityOrdered接口

  2. 实现org.springframework.core.Ordered接口

执行顺序:

PriorityOrdered.getOrder() asc,Ordered.getOrder() asc

下面通过案例来感受一下效果。

案例

这个案例中演示,在BeanFactoryPostProcessor来修改bean中已经注册的bean定义的信息,给一个bean属性设置一个值。

先来定义一个bean

package com.javacode2018.lesson003.demo3.test2;

import org.springframework.stereotype.Component;

@Component
public class LessonModel {
    //课程名称
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "LessonModel{" +
                "name='" + name + '\'' +
                '}';
    }
}

上面这个bean有个name字段,并没有设置值,下面我们在BeanFactoryPostProcessor来对其设置值。

自定义的BeanFactoryPostProcessor

下面代码中,我们先获取lessonModel这个bean的定义信息,然后给其name属性设置了一个值。

package com.javacode2018.lesson003.demo3.test2;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("准备修改lessonModel bean定义信息!");
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("lessonModel");
        beanDefinition.getPropertyValues().add("name", "spring高手系列!");
    }

}

测试用例

@Test
public void test2() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.register(MainConfig2.class);
    context.refresh();

    System.out.println(context.getBean(LessonModel.class));
}

运行输出

准备修改lessonModel bean定义信息!
LessonModel{name='spring高手系列!'}

结果中可以看出,通过BeanFactoryPostProcessor修改了容器中已经注册的bean定义信息。

这个接口的几个重要实现类

PropertySourcesPlaceholderConfigurer

这个接口做什么的,大家知道么?来看一段代码

<bean class="xxxxx">
    <property name="userName" value="${userName}"/>
    <property name="address" value="${address}"/>
</bean>

这个大家比较熟悉吧,spring就是在PropertySourcesPlaceholderConfigurer#postProcessBeanFactory中来处理xml中属性中的${xxx},会对这种格式的进行解析处理为真正的值。

CustomScopeConfigurer

向容器中注册自定义的Scope对象,即注册自定义的作用域实现类,关于自定义的作用域,不了解的朋友,建议先看一下:Spring系列第6篇:玩转bean scope,避免跳坑里!

这个用法比较简单,定义一个CustomScopeConfigurer的bean就可以了,然后通过这个类来注册自定义的bean。

EventListenerMethodProcessor

处理@EventListener注解的,即spring中事件机制,需要了解spring事件的:spring事件机制详解

还有一些实现类,这里就不介绍了。

使用注意

BeanFactoryPostProcessor接口的使用有一个需要注意的地方,在其postProcessBeanFactory方法中,强烈禁止去通过容器获取其他bean,此时会导致bean的提前初始化,会出现一些意想不到的问题,因为这个阶段中BeanPostProcessor还未准备好,本文开头4个阶段中有介绍,BeanPostProcessor是在第3个阶段中注册到spring容器的,而BeanPostProcessor可以对bean的创建过程进行干预,比如spring中的aop就是在BeanPostProcessor的一些子类中实现的,@Autowired也是在BeanPostProcessor的子类中处理的,此时如果去获取bean,此时bean不会被BeanPostProcessor处理,所以创建的bean可能是有问题的,还是通过一个案例给大家演示一下把,通透一些。

来一个简单的类

package com.javacode2018.lesson003.demo3.test3;

import org.springframework.beans.factory.annotation.Autowired;

public class UserModel {
    @Autowired
    private String name; //@1

    @Override
    public String toString() {
        return "UserModel{" +
                "name='" + name + '\'' +
                '}';
    }
}

@1:使用了@Autowired,会指定注入

来个配置类

配置类中定义了2个UserModel类型的bean:user1、user2

并且定义了一个String类型的bean:name,这个会注入到UserModel中的name属性中去。

package com.javacode2018.lesson003.demo3.test3;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan
public class MainConfig3 {
    @Bean
    public UserModel user1() {
        return new UserModel();
    }

    @Bean
    public UserModel user2() {
        return new UserModel();
    }

    @Bean
    public String name() {
        return "路人甲Java,带大家成功java高手!";
    }
}

测试用例

输出容器中所有UserModel类型的bean

@Test
public void test3() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.register(MainConfig3.class);
    context.refresh();

    context.getBeansOfType(UserModel.class).forEach((beanName, bean) -> {
        System.out.println(String.format("%s->%s", beanName, bean));
    });
}

运行输出

user1->UserModel{name='路人甲Java,带大家成功java高手!'}
user2->UserModel{name='路人甲Java,带大家成功java高手!'}

效果不用多解释,大家一看就懂,下面来重点。

添加一个BeanFactoryPostProcessor

postProcessBeanFactory方法中去获取一下user1这个bean

package com.javacode2018.lesson003.demo3.test3;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        beanFactory.getBean("user1");
    }

}

再次运行输出

user1->UserModel{name='null'}
user2->UserModel{name='路人甲Java,带大家成功java高手!'}

注意,user1中的name变成null了,什么情况?

是因为@Autowired注解是在AutowiredAnnotationBeanPostProcessor中解析的,spring容器调用BeanFactoryPostProcessor#postProcessBeanFactory的使用,此时spring容器中还没有AutowiredAnnotationBeanPostProcessor,所以此时去获取user1这个bean的时候,@Autowired并不会被处理,所以name是null。

源码

4个阶段的源码

4个阶段的源码为位于下面这个方法中

org.springframework.context.support.AbstractApplicationContext#refresh

这个方法中截取部分代码如下:

// 对应阶段1和阶段2:调用上下文中注册为bean的工厂处理器,即调用本文介绍的2个接口中的方法
invokeBeanFactoryPostProcessors(beanFactory);

// 对应阶段3:注册拦截bean创建的bean处理器,即注册BeanPostProcessor
registerBeanPostProcessors(beanFactory);

// 对应阶段3:实例化所有剩余的(非延迟初始化)单例。
finishBeanFactoryInitialization(beanFactory);

阶段1和阶段2的源码位于下面方法中,代码比较简单,强烈建议大家去看一下,几分钟就可以看懂了。

org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List<org.springframework.beans.factory.config.BeanFactoryPostProcessor>)

总结

  1. 注意spring的4个阶段:bean定义阶段、BeanFactory后置处理阶段、BeanPostProcessor注册阶段、单例bean创建组装阶段

  2. BeanDefinitionRegistryPostProcessor会在第一个阶段被调用,用来实现bean的注册操作,这个阶段会完成所有bean的注册

  3. BeanFactoryPostProcessor会在第2个阶段被调用,到这个阶段时候,bean此时已经完成了所有bean的注册操作,这个阶段中你可以对BeanFactory中的一些信息进行修改,比如修改阶段1中一些bean的定义信息,修改BeanFactory的一些配置等等

  4. 阶段2的时候,2个禁止操作:禁止注册bean、禁止从容器中获取bean

  5. 本文介绍的2个接口的实现类可以通过PriorityOrdered接口或者Ordered接口来指定顺序

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring系列之BeanFactory扩展(BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor) 的相关文章

  • 通过SOCKS代理连接Kafka

    我有一个在 AWS 上运行的 Kafka 集群 我想用标准连接到集群卡夫卡控制台消费者从我的应用程序服务器 应用程序服务器可以通过 SOCKS 代理访问互联网 无需身份验证 如何告诉 Kafka 客户端通过代理进行连接 我尝试了很多事情 包
  • 使用 GWT 读取非常大的本地 XML 文件

    我正在使用 GWT 构建我的第一个 Java 应用程序 它必须从一个非常大的 XML 文件中读取数据 当我尝试发送对文件中信息的请求时遇到问题 并且我不太确定它是否与文件的大小或我的语义有关 在我的程序中 我有以下内容 static fin
  • 如何在 Antlr4 中为零参数函数编写语法

    我的函数具有参数语法 如下面的词法分析器和解析器 MyFunctionsLexer g4 lexer grammar MyFunctionsLexer FUNCTION FUNCTION NAME A Za z0 9 DOT COMMA L
  • Java:在 eclipse 中导出到 .jar 文件

    我正在尝试将 Eclipse 中的程序导出到 jar 文件 在我的项目中 我添加了一些图片和 PDF s 当我导出到 jar 文件时 似乎只有main已编译并导出 我的意愿是如果可能的话将所有内容导出到 jar 文件 因为这样我想将其转换为
  • Spring Boot自动装配存储库始终为空[重复]

    这个问题在这里已经有答案了 每次我进入我的服务类时 存储库似乎都没有自动连接 因为它不断抛出 NullPointerException 谁能帮我检查一下我缺少什么吗 这是我的代码 演示应用程序 java package com exampl
  • 在 Wildfly 中与 war 部署共享 util jar 文件

    假设我有一个名为 util jar 的 jar 文件 该 jar 文件主要包含 JPA 实体和一些 util 类 无 EJB 如何使这个 jar 可用于 Wildfly 中部署的所有 war 无需将 jar 放置在 war 的 WEB IN
  • Kotlin 未解决的参考:CLI 上 gradle 的 println

    放一个printlnkotlin 函数返回之前的语句会崩溃 堆栈跟踪 thufir dur NetBeansProjects kotlin thufir dur NetBeansProjects kotlin gradle clean bu
  • 如何根据运行的 jar 的结果让我的 ant 任务通过或失败?

    我正在运行 CrossCheck 无浏览器 js 单元测试 作为 ant 脚本的一部分 如果 CrossCheck 测试失败 我希望 ant 报告失败 这是 build xml 中的相关部分
  • Spring 规范 - 谓词的联合

    我需要一个函数来过滤参数并构建查询 我有 4 个参数 因此如果我尝试为每个条件实现查询 我将不得不编写 16 2 4 实施 这不是一个好主意 我尝试通过界面改进我的代码Specification来自 Spring Data JPA 但我无法
  • 使用 JUnit 时,有没有办法验证测试方法中是否调用了 try/catch 指令的 Catch 部分?

    例如 如果我想测试以下课程 public class SomeClass public void someMethod try Some code where comething could go wrong catch Exception
  • 自动生成Flyway的迁移SQL

    当通过 Java 代码添加新模型 字段等时 JPA Hibernate 的自动模式生成是否可以生成新的 Flyway 迁移 捕获自动生成的 SQL 并将其直接保存到新的 Flyway 迁移中 以供审查 编辑 提交到项目存储库 这将很有用 预
  • 套接字的读写如何同步?

    我们创建一个套接字 在套接字的一侧有一个 服务器 在另一侧有一个 客户端 服务器和客户端都可以向套接字写入和读取 这是我的理解 我不明白以下事情 如果服务器从套接字读取数据 它在套接字中是否只看到客户端写入套接字的内容 我的意思是 如果服务
  • 使用 Guice 优化注册表

    你好 今天思考了一种优化 有一些疑问 语境 我正在使用 Guice 2 进行 Java 开发 在我的网络应用程序中 我有一个转换器注册表 可以即时转换为某种类型 转换器描述如下 public class StringToBoolean im
  • @Autowire注释的问题(空)

    我在验证器类中自动连接的两个服务有问题 这些服务工作正常 因为在我的控制器中是自动连接的 我有一个 applicationContext xml 文件和 MyApp servlet xml 文件 我的基础包是 es unican meteo
  • 了解joda时间PeriodFormatter

    我以为我明白了 但显然我不明白 你能帮我通过这些单元测试吗 Test public void second assertEquals 00 00 01 OurDateTimeFormatter format 1000 Test public
  • 返回 Java 8 中的通用函数接口

    我想写一种函数工厂 它应该是一个函数 以不同的策略作为参数调用一次 它应该返回一个函数 该函数根据参数选择其中一种策略 该参数将由谓词实现 嗯 最好看看condition3为了更好的理解 问题是 它没有编译 我认为因为编译器无法弄清楚函数式
  • 使用布尔值进行冒泡排序以确定数组是否已排序

    我有以下用于冒泡排序的代码 但它根本不排序 如果我删除布尔值那么它工作正常 我知道 由于我的 a 0 小于所有其他元素 因此没有执行交换 任何人都可以帮助我解决这个问题 package com sample public class Bub
  • 在 Google App-Engine JAVA 中将文本转换为字符串,反之亦然

    如何从字符串转换为文本 java lang String to com google appengine api datastore Text 反之亦然 Check Javadoc http code google com appengin
  • Java EE 目录结构

    我对以下教程有疑问 http www mkyong com jsf2 jsf 2 internationalization example http www mkyong com jsf2 jsf 2 internationalizatio
  • 在java中使用多个bufferedImage

    我正在 java 小程序中制作游戏 并且正在尝试优化我的代码以减少闪烁 我已经实现了双缓冲 因此我尝试使用另一个 BufferedImage 来存储不改变的游戏背景元素的图片 这是我的代码的相关部分 public class QuizApp

随机推荐

  • ceph 维护系列(二)--卸载osd

    一 摘要 本文主要介绍从ceph 某台节点上卸载一块或者多块osd 硬盘 二 环境信息 2 1 操作系统版本 root proceph05 cat etc centos release CentOS Linux release 7 6 18
  • SSM框架搭建,及遇到的问题

    SSM框架搭建 及遇到的问题 1 基本概念 1 1 Spring Spring是一个开源框架 Spring是于2003 年兴起的一个轻量级的Java 开发框架 由Rod Johnson 在其著作Expert One On One J2EE
  • 使用NNI对BERT模型进行粗剪枝、蒸馏与微调

    前言 模型剪枝 Model Pruning 是一种用于减少神经网络模型尺寸和计算复杂度的技术 通过剪枝 可以去除模型中冗余的参数和连接 从而减小模型的存储需求和推理时间 同时保持模型的性能 模型剪枝的一般步骤 训练初始模型 训练一个初始的神
  • win10 WSL2 Ubuntu图像化界面安装和配置

    1 win11 设置 打开虚拟机安装许可 2 开启开发者模式 2 Microsoft Store下载安装ubuntu 我这里使用的是20 04 5LTS版本 3 打开ubuntu 命令窗口 1 打开win11的命令行 在下拉三角下标 打开
  • 【云原生之Docker实战】使用Docker部署宝塔面板

    云原生之Docker实战 使用Docker部署宝塔面板 一 宝塔面板介绍 二 检查本地docker环境 1 检查系统版本 2 检查内核版本 3 检查docker版本 三 下载宝塔镜像 四 部署宝塔面板 1 创建挂载目录 2 创建宝塔容器 3
  • 四、C++语言进阶:Boost入门

    4 Boost入门 4 1 简介 Boost库是一个可移植 提供源代码的C 库 作为标准库的后备 是C 标准化进程的开发引擎之一 是为C 语言标准库提供扩展的一些C 程序库的总称 4 2 使用 4 2 1 lamdba表达式 lambda库
  • 字符设备

    from here 字符设备http blog 163 com sunshine linting blog static 44893323201181102957282 字符设备是一种按字节来访问的设备 字符驱动则负责驱动字符设备 这样的驱
  • C++Static成员

    Static成员 概念 声明为static的类成员称为类的静态成员 用static修饰的成员变量 称之为静态成员变量 用static修饰的成员函数 称之为静态成员函数 静态成员变量一定要在类外进行初始化 例题 实现一个类 计算程序中创建了多
  • Mysql索引原理

    Mysql索引类型及其特性 1 普通索引 最基本的索引 它没有任何限制 也是我们大多数情况下用到的索引 直接创建索引 CREATE INDEX index name ON table column length 修改表结构的方式添加索引 A
  • Linux深度系统分区顺序,深度Deepin 20操作系统默认全盘分区不合理?附建设性意见探讨...

    有的网友认为深度 Deepin 20 操作系统默认全盘分区不合理 以下是某位深度网友的个人意见 首先 必须认为默认全盘分区的确存在一些不合理 以下是建设性意见 供与网友们一起探讨 建设性意见内容如下 1 EFI 引导分区 315M 实际使用
  • Javascript模块化规范之CommonJs,AMD,CMD

    Javascript模块化编程规范 一 模块化编程背景 1 什么是模块化编程 2 Javascript模块化编程有哪些规范 二 Javascript模块化编程 1 CommonJs 2 AMD异步模块定义 3 CMD 通用模块定义 4 ES
  • printf()函数

    printf函数对输出表中各量求值的顺序是自右至左进行的 也即程序执行的过程中参数的压栈顺序是从右至左的 并且压栈时压入的是值 因为参数的压栈是在程序的执行过程中 所以即使参数列表中有函数调用则在压栈时也即计算出来 即调用此函数去执行 把得
  • MathType改变字体大小

    目录 一 MathType中的公式字体 二 临时自定义字体大小 三 更改默认字体大小 四 总结 一 MathType中的公式字体 MathType中默认的字体大小为12pt 在word中即小四 word字体对应MathType的字体大小如下
  • Android Studio开发环境的搭建

    Android Studio开发环境的搭建 一 实验目的及任务 Windows下掌握Android Studio的安装和配置 模拟器的创建 Activity的创建和注册 二 实验环境 Jdk Android Studio 三 实验步骤 An
  • 7 种提升SpringBoot 吞吐量神技

    架构师专栏 2022 04 11 08 44 大家好 我是磊哥 一 异步执行 实现方式二种 1 使用异步注解 aysnc 启动类 添加 EnableAsync注解 2 JDK 8本身有一个非常好用的Future类 CompletableFu
  • 计算两个数之和,不能用+ = 运算符

    在lintcode的一个简单的算法题 计算两数的和 不能用 运算符 对于这个题 我是一点思路都没有 不用 那能用什么计算呢 于是在网上找了找答案 答案其实很简单 主要是涉及到运算 我是觉得应该记一下 所以才将这个题写下来 具体代码 异或 运
  • centos 6.5 连接MySQL 提示:ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password:

    centos 6 5 连接MySQL 提示 ERROR 1045 28000 Access denied for user root localhost using password NO CentOs 第一次登入MySQL 默认超级用户
  • 深度学习中的优化算法之AdaGrad

    之前在https blog csdn net fengbingchun article details 123955067 介绍过SGD Mini Batch Gradient Descent MBGD 有时提到SGD的时候 其实指的是MB
  • 链表和线性表的优缺点

    链表和线性表的优缺点 作为我们最先接触的两个数据结构 链表和线性表的优缺点都较为明显 并且二者互相补足 文章目录 链表和线性表的优缺点 线性表 线性表的组成 线性表的缺点 线性表的优点 链表 链表的组成 链表的优点 链表的缺点 总结 线性表
  • Spring系列之BeanFactory扩展(BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor)

    先来看几个问题 BeanFactoryPostProcessor是做什么的 BeanDefinitionRegistryPostProcessor是干什么的 BeanFactoryPostProcessor和BeanDefinitionRe