七种 BeanDefinition,各显其能!

news2024/7/6 17:49:20

聚沙成塔!不知不觉 Spring 源码已经连续更了两个月啦,视频也录制了不少了,对 Spring 源码分析感兴趣的小伙伴戳这里哦Spring源码应该怎么学?~

今天我们继续来看 Spring 源码中一个非常重要的概念:BeanDefinition。

1.BeanDefinition

在 Spring 容器中,我们广泛使用的是一个一个的 Bean,BeanDefinition 从名字上就可以看出是关于 Bean 的定义。

事实上就是这样,我们在 XML 文件中配置的 Bean 的各种属性,亦或者用注解定义出来的 Bean 的各种属性,在真正生成 Bean 直接,我们需要先对这些设置的属性进行解析,解析的结果需要有一个对象来承载,很明显,这个对象就是 BeanDefinition。

无论是通过 XML 中定义的 Bean 属性还是通过 Java 代码定义的 Bean 属性,都会先加载到 BeanDefinition 上,然后通过 BeanDefinition 来生成一个 Bean,从这个角度来说,BeanDefinition 和 Bean 的关系有点类似于类和对象的关系,BeanDefinition 是模板,Bean 是模板具体化之后的产物。

要理解 BeanDefinition,我们从 BeanDefinition 的继承关系开始看起。

BeanDefinition 是一个接口,继承自 BeanMetadataElement 和 AttributeAccessor 接口。

  • BeanMetadataElement:该接口只有一个方法 getSource,该方法返回 Bean 的来源。
  • AttributeAccessor:该接口主要规范了问任意对象元数据的方法。

我们来看下 AttributeAccessor:

public interface AttributeAccessor {
	void setAttribute(String name, @Nullable Object value);
	@Nullable
	Object getAttribute(String name);
	@Nullable
	Object removeAttribute(String name);
	boolean hasAttribute(String name);
	String[] attributeNames();
}

这里定义了元数据的访问接口,具体的实现则是 AttributeAccessorSupport,这些数据采用 LinkedHashMap 进行存储。

这是 BeanDefinition 所继承的两个接口。接下来我们来看下 BeanDefinition 接口:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
	String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
	String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
	int ROLE_APPLICATION = 0;
	int ROLE_SUPPORT = 1;
	int ROLE_INFRASTRUCTURE = 2;
	void setParentName(@Nullable String parentName);
	@Nullable
	String getParentName();
	void setBeanClassName(@Nullable String beanClassName);
	@Nullable
	String getBeanClassName();
	void setScope(@Nullable String scope);
	@Nullable
	String getScope();
	void setLazyInit(boolean lazyInit);
	boolean isLazyInit();
	void setDependsOn(@Nullable String... dependsOn);
	@Nullable
	String[] getDependsOn();
	void setAutowireCandidate(boolean autowireCandidate);
	boolean isAutowireCandidate();
	void setPrimary(boolean primary);
	boolean isPrimary();
	void setFactoryBeanName(@Nullable String factoryBeanName);
	@Nullable
	String getFactoryBeanName();
	void setFactoryMethodName(@Nullable String factoryMethodName);
	@Nullable
	String getFactoryMethodName();
	ConstructorArgumentValues getConstructorArgumentValues();
	default boolean hasConstructorArgumentValues() {
		return !getConstructorArgumentValues().isEmpty();
	}
	MutablePropertyValues getPropertyValues();
	default boolean hasPropertyValues() {
		return !getPropertyValues().isEmpty();
	}
	void setInitMethodName(@Nullable String initMethodName);
	@Nullable
	String getInitMethodName();
	void setDestroyMethodName(@Nullable String destroyMethodName);
	@Nullable
	String getDestroyMethodName();
	void setRole(int role);
	int getRole();
	void setDescription(@Nullable String description);
	@Nullable
	String getDescription();
	ResolvableType getResolvableType();
	boolean isSingleton();
	boolean isPrototype();
	boolean isAbstract();
	@Nullable
	String getResourceDescription();
	@Nullable
	BeanDefinition getOriginatingBeanDefinition();
}

BeanDefinition 中的方法虽然多,但是结合我们平时在 XML/Java 中的配置,这些方法其实都很好理解:

  1. 首先一开始定义了两个变量用来描述 Bean 是不是单例的,后面的 setScope/getScope 方法可以用来修改/获取 scope 属性。
  2. ROLE_xxx 用来描述一个 Bean 的角色,ROLE_APPLICATION 表示这个 Bean 是用户自己定义的 Bean;ROLE_SUPPORT 表示这个 Bean 是某些复杂配置的支撑部分;ROLE_INFRASTRUCTURE 表示这是一个 Spring 内部的 Bean,通过 setRole/getRole 可以修改。
  3. setParentName/getParentName 用来配置 parent 的名称,这块可能有的小伙伴使用较少,这个对应着 XML 中的 <bean parent=""> 配置,在之前的视频中松哥已经和大家讲过了 Spring 中 parent 的使用了。
  4. setBeanClassName/getBeanClassName 这个就是配置 Bean 的 Class 全路径,对应 XML 中的 <bean class=""> 配置。
  5. setLazyInit/isLazyInit 配置/获取 Bean 是否懒加载,这个对应了 XML 中的 <bean lazy-init=""> 配置。
  6. setDependsOn/getDependsOn 配置/获取 Bean 的依赖对象,这个对应了 XML 中的 <bean depends-on=""> 配置。
  7. setAutowireCandidate/isAutowireCandidate 配置/获取 Bean 是否是自动装配,对应了 XML 中的 <bean autowire-candidate=""> 配置。
  8. setPrimary/isPrimary 配置/获取当前 Bean 是否为首选的 Bean,对应了 XML 中的 <bean primary=""> 配置。
  9. setFactoryBeanName/getFactoryBeanName 配置/获取 FactoryBean 的名字,对应了 XML 中的 <bean factory-bean=""> 配置,factory-bean 松哥在之前的视频中讲过,小伙伴们可以参考这里:Spring源码应该怎么学?。
  10. setFactoryMethodName/getFactoryMethodName 和上一条成对出现的,对应了 XML 中的 <bean factory-method=""> 配置,不再赘述。
  11. getConstructorArgumentValues 返回该 Bean 构造方法的参数值。
  12. hasConstructorArgumentValues 判断上一条是否是空对象。
  13. getPropertyValues 这个是获取普通属性的集合。
  14. hasPropertyValues 判断上一条是否为空对象。
  15. setInitMethodName/setDestroyMethodName 配置 Bean 的初始化方法、销毁方法。
  16. setDescription/getDescription 配置/返回 Bean 的描述。
  17. isSingleton Bean 是否为单例。
  18. isPrototype Bean 是否为原型。
  19. isAbstract Bean 是否抽象。
  20. getResourceDescription 返回定义 Bean 的资源描述。
  21. getOriginatingBeanDefinition 如果当前 BeanDefinition 是一个代理对象,那么该方法可以用来返回原始的 BeanDefinition 。

这个就是 BeanDefinition 的定义以及它里边方法的含义。

2.BeanDefinition 实现类

上面只是 BeanDefinition 接口的定义,BeanDefinition 还拥有诸多实现类,我们也来大致了解下。

先来看一张继承关系图:

这么多实现类看着有点眼花缭乱,不过搞清楚了每一个接口和类的作用,再看就很容易了。

2.1 AbstractBeanDefinition

AbstractBeanDefinition 是一个抽象类,它根据 BeanDefinition 中定义的接口提供了相应的属性,并实现了 BeanDefinition 中定义的一部分方法。BeanDefinition 中原本只是定义了一系列的 get/set 方法,并没有提供对应的属性,在 AbstractBeanDefinition 中将所有的属性定义出来了。

后面其他的实现类也基本上都是在 AbstractBeanDefinition 的基础上完成的。

2.2 RootBeanDefinition

这是一个比较常用的实现类,对应了一般的元素标签。

2.3 ChildBeanDefinition

可以让子 BeanDefinition 定义拥有从父 BeanDefinition 那里继承配置的能力,如果子 Bean 从父 Bean 获取配置,可以参考松哥之前的这篇文章:Spring BeanDefinition 也分父子?。

2.4 GenericBeanDefinition

GenericBeanDefinition 是从 Spring2.5 以后新加入的 BeanDefinition 实现类。GenericBeanDefinition 可以动态设置父 Bean,同时兼具 RootBeanDefinition 和 ChildBeanDefinition 的功能,因此,自从有了 GenericBeanDefinition 之后,RootBeanDefinition 和 ChildBeanDefinition 现在相对就用的少了。

2.5 AnnotatedBeanDefinition

这个表示注解类型 BeanDefinition,用于表示通过注解配置的 Bean 定义。通过 AnnotatedBeanDefinition,我们可以获取到被注解的 Bean 的相关信息,包括注解类型、属性值、方法等。这个接口提供了一种方便的方式来处理通过注解方式配置的 Bean,并且可以在运行时动态地获取和操作这些注解信息,当然,这是一个接口,它有三个实现类,分别是 AnnotatedGenericBeanDefinition、ScannedGenericBeanDefinition 以及 ConfigurationClassBeanDefinition。

2.6 AnnotatedGenericBeanDefinition

作为系统配置类的类会解析为 AnnotatedGenericBeanDefinition。

2.7 ScannedGenericBeanDefinition

这个是通过包扫描自动注册的 Bean,就会被解析为 ScannedGenericBeanDefinition。

2.8 ConfigurationClassBeanDefinition

这是一个私有的内部类。我们通过 @Bean 注解定义的 Bean,最终会被解析为 ConfigurationClassBeanDefinition。

2.9 ClassDerivedBeanDefinition

ClassDerivedBeanDefinition 的作用是扩展并描述一个类派生的Bean的元数据。它是 AnnotatedBeanDefinition 接口的一个实现类,在 Spring 框架中用于表示通过类派生方式配置的Bean定义。

2.10 CreateFromClassBeanDefinition

这个是按照类型创建 Bean 的时候会用到。

差不多就这么多了,大部分我们日常开发中其实都用不上,接下来松哥通过几个具体的案例来和小伙伴们演示这些 BeanDefinition 的具体用法。后面的文章,我们再来分析这些 BeanDefinition 在 Spring 源码中是如何应用的。

3.实践

接下来我通过几个具体的案例来和小伙伴们演示各种不同的 BeanDefinition 的用法,今天我主要和小伙伴们演示我们纯手动使用 BeanDefinition,然后分析一下我们平时的配置本质上使用的 BeanDefinition 是哪一个,今天我们先不去源码分析,单纯的就看看效果。

3.1 GenericBeanDefinition

先来看 GenericBeanDefinition,这个功能相对比较全,兼具 RootBeanDefinition 和 ChildBeanDefinition 的能力。

先来看一个简单用法:

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setBeanClass(User.class);
MutablePropertyValues pValues = new MutablePropertyValues();
pValues.add("username", "javaboy");
bd.setPropertyValues(pValues);
beanFactory.registerBeanDefinition("user", bd);
User user = beanFactory.getBean("user", User.class);
System.out.println("user = " + user);

小伙伴们看到,我们这里向 Spring 容器注册了一个 GenericBeanDefinition 类型的 BeanDefinition,GenericBeanDefinition 中包含了具体的 class 以及 Bean 的各个属性值。

如果我们在 Bean 定义的时候,想要使用继承特性,也可以使用 GenericBeanDefinition:

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
GenericBeanDefinition parentBD = new GenericBeanDefinition();
GenericBeanDefinition childBD = new GenericBeanDefinition();
parentBD.setBeanClass(Animal.class);
MutablePropertyValues pValues = new MutablePropertyValues();
pValues.add("name", "小黄");
parentBD.setPropertyValues(pValues);
childBD.setBeanClass(Dog.class);
childBD.setParentName("animal");
beanFactory.registerBeanDefinition("animal", parentBD);
beanFactory.registerBeanDefinition("dog", childBD);
Dog dog = beanFactory.getBean("dog", Dog.class);
System.out.println("dog = " + dog);

这次我直接定义了两个 GenericBeanDefinition,一个作为 parent,另外一个作为 child,为 child 设置 parentName,则 child 可以继承 parent 中的属性。上面的案例中,最终打印出来 dog 的 name 属性就是 小黄,这块小伙伴们可以参考松哥之前的文章:Spring BeanDefinition 也分父子?。

我们平时通过 XML 文件定义的 Bean,最终解析后就是 GenericBeanDefinition。

例如下面这样:

<?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/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="org.javaboy.demo.User" id="user"></bean>
</beans>

加载 XML 文件,创建容器:

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
    BeanDefinition bd = ctx.getBeanFactory().getBeanDefinition(beanDefinitionName);
    System.out.println(beanDefinitionName + ">>>" + bd.getClass());
}

最终打印结果如下:

这个也好理解,毕竟我们在 XML 中配置的时候,可能存在 parent,也可能不存在,用 GenericBeanDefinition 就能够应对各种情况。

3.2 RootBeanDefinition/ChildBeanDefinition

这两个常规的功能其实都有,但是 RootBeanDefinition 一般可以用来做 parent,不能用作 child,即给 RootBeanDefinition 不能配置 parentName 属性。强行设置会抛出如下异常:

@Override
public void setParentName(@Nullable String parentName) {
	if (parentName != null) {
		throw new IllegalArgumentException("Root bean cannot be changed into a child bean with parent reference");
	}
}

ChildBeanDefinition 则既可以做 parent 也可以做 child,但是 ChildBeanDefinition 在使用的使用必须指定 parent,即使 ChildBeanDefinition 作为 parent,也必须指定 parent,所以 ChildBeanDefinition 在使用的过程中有一点点局限性,因此目前被 GenericBeanDefinition 代替了。

来看一个简单的案例:

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
RootBeanDefinition parentBD = new RootBeanDefinition();
parentBD.setBeanClass(Animal.class);
MutablePropertyValues pValues = new MutablePropertyValues();
pValues.add("name", "小黄");
parentBD.setPropertyValues(pValues);
ChildBeanDefinition childBD = new ChildBeanDefinition("animal");
childBD.setBeanClass(Dog.class);
beanFactory.registerBeanDefinition("animal", parentBD);
beanFactory.registerBeanDefinition("dog", childBD);
Dog dog = beanFactory.getBean("dog", Dog.class);
System.out.println("dog = " + dog);

3.3 AnnotatedGenericBeanDefinition

对于使用 @Configuration 注解标记的类,最终解析出来的 BeanDefinition 就是 AnnotatedGenericBeanDefinition。例如我有一个配置类如下:

@Configuration
public class JavaConfig {

}

加载配置类并启动容器:

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
    BeanDefinition beanDefinition = ctx.getBeanFactory().getBeanDefinition(beanDefinitionName);
    System.out.println(beanDefinitionName + " >>> " + beanDefinition.getClass());
}

最终打印结果如下:

3.4 ScannedGenericBeanDefinition

这个是那些通过包扫描注册到 Spring 容器中的 Bean,在一开始定义出来的 BeanDefinition 就是 ScannedGenericBeanDefinition。

例如我有如下 Bean:

@Service
public class UserService {

}

然后配置包扫描:

@Configuration
@ComponentScan
public class JavaConfig {
}

启动容器:

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
    BeanDefinition beanDefinition = ctx.getBeanFactory().getBeanDefinition(beanDefinitionName);
    System.out.println(beanDefinitionName + " >>> " + beanDefinition.getClass());
}

最终打印结果如下:

3.5 ConfigurationClassBeanDefinition

当我们通过 @Bean 注解去定义 Bean 的时候,那么被 @Bean 注解标记的类就会被解析为 ConfigurationClassBeanDefinition。

例如下面这个例子:

@Configuration
public class JavaConfig {
    @Bean
    User user() {
        return new User();
    }
}

查看解析后的 BeanDefinition 如下:

3.6 CreateFromClassBeanDefinition

这个其实用的少,但是咱么既然讲到 Spring,松哥也说两句。

这个是当我们想要创建一个对象,我们希望这个对象能够自动走一遍 Spring 中的各种后置处理器的时候,那么可以调用 createBean 方法,该方法内部使用了 CreateFromClassBeanDefinition。

例如如下代码:

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
ConfigurableListableBeanFactory beanFactory = ctx.getBeanFactory();
User user = beanFactory.createBean(User.class);
System.out.println("user = " + user);

使用这种方式去创建一个 Bean,这个 Bean 会走一遍 Spring 中 Bean 的后置处理器,其中,createBean 方法的内部就使用了 CreateFromClassBeanDefinition。

3.7 ClassDerivedBeanDefinition

ClassDerivedBeanDefinition 和 CreateFromClassBeanDefinition 其实比较像,差别在于二者处理构造方法的方式不同。

而且 ClassDerivedBeanDefinition 是一个相当冷门的 BeanDefinition,在 GenericApplicationContext 的实现类中,可以使用 GenericXmlApplicationContext、StaticApplicationContext 或者 GenericGroovyApplicationContext,只有这三个类中 registerBean 方法用到了 ClassDerivedBeanDefinition,我们常见的 AnnotationConfigApplicationContext 由于方法重写的缘故并未使用 ClassDerivedBeanDefinition。

StaticApplicationContext ctx = new StaticApplicationContext();
ctx.registerBean(User.class,()->{
    User user = new User();
    user.setUsername("javaboy");
    return user;
});
User user = ctx.getBean(User.class);
System.out.println("user = " + user);
String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
    BeanDefinition bd = ctx.getBeanDefinition(beanDefinitionName);
    System.out.println(beanDefinitionName + ">>>" + bd.getClass());
}

我们可以调用 registerBean 方法向 Spring 容器中注入一个 Bean,该方法第二个参数是一个 Bean 的生产者,如果不指定生产者,那么这个方法最终就是通过第一个参数反射创建 Bean,registerBean 方法的内部就是使用了 ClassDerivedBeanDefinition。

好啦,BeanDefinition 一共就是这七种,接下来我会通过几篇文章和大家重点介绍 GenericBeanDefinition、AnnotatedGenericBeanDefinition、ScannedGenericBeanDefinition 以及 ConfigurationClassBeanDefinition 这四种最为常见的 BeanDefinition。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/992450.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

万物皆可连的腾讯轻联

文章目录 前言关于腾讯轻联小试牛刀新建流程配置逻辑组件配置连接器流程上线 其它功能核心能力总结 前言 工作中有这样一个需求&#xff0c;每周五下午三点定时给小组内成员发送邮件&#xff0c;邮件内容固定&#xff0c;主要作用是提醒大家记得发周报&#xff1b;其实这个需求…

iOS:解决Could not find a storyboard named ‘LaunchScreen.storyboard‘ in bundle NSBundle

打开项目的&#xff1a;HBuilder-uniPlugin-Info.plist 删除Launch screen interface file base name 然后看图&#xff0c;清空掉之前的LaunchScreen.storyboard东西 再运行就可以了&#xff0c;我也是改自定基座出的问题略

西门子LAD编程扫描周期带来的步序跳转问题

一、程序目的 按一下启动&#xff0c;程序进入第一步。延时五秒之后进入第二步进行自加1&#xff0c;然后回到第一步继续延时5秒循环&#xff0c;依次类推。 二、出现的问题 第一次程序进入第一步时&#xff0c;定时器正常定时&#xff0c;计数正常加1&#xff0c;但从第二轮开…

使用WinDbg进行动态调试

前言 本文章主要介绍如何使用WinDbg进行动态调试。如果程序崩溃后&#xff0c;没有记录dump文件&#xff0c;或者程序启动时发生异常&#xff0c;比如常见的 应用程序无法正常启动(0xc000007b) 报错&#xff0c;都可以使用WinDbg动态调试功能来定位问题。文章最后&#xff0c;…

用go实现一个循环队列

目录 队列数组队列的“假溢出”现象循环队列三种判断队列空和满的方法无下标&#xff08;链式&#xff09;有下标&#xff08;顺序&#xff09;长度标记 go用顺序表实现一个循环队列队列的链式存储结构 队列 队列&#xff08;queue&#xff09;是只允许在一端进行插入操作&…

物联网世界的无线电报之MQTT详解

文章目录 1. 前言1.1. 物联网与MQTT的关系1.2. MQTT的重要性及应用场景 2. MQTT基础2.1. MQTT的定义与起源2.2. MQTT的工作原理2.3. MQTT的协议格式2.4. 用java造个轮子 3. 深入理解MQTT3.1. MQTT的主要组件3.1.1. Publisher&#xff08;发布者&#xff09;3.1.2. Subscriber&a…

RTSP流媒体服务器EasyNVR视频平台以服务方式启动异常却无报错,该如何解决?

EasyNVR是基于RTSP/Onvif协议的安防视频云服务平台&#xff0c;可实现设备接入、实时直播、录像、检索与回放、云存储、视频分发、级联等视频能力服务&#xff0c;可覆盖全终端平台&#xff08;电脑、手机、平板等终端&#xff09;&#xff0c;在智慧工厂、智慧工地、智慧社区、…

【2023微博评论爬虫】用python爬上千条微博评论,突破15页限制!

文章目录 一、爬取目标二、展示爬取结果三、爬虫代码四、同步视频五、获取完整源码 您好&#xff0c;我是 马哥python说&#xff0c;一枚10年程序猿。 一、爬取目标 前些天我分享过一篇微博的爬虫&#xff1a; 马哥python说&#xff1a;【python爬虫案例】爬取微博任意搜索关…

【网络编程】IO多路复用

IO多路复用是一种高效的I/O处理方式&#xff0c;它允许单个进程能够同时监视多个文件描述符&#xff08;sockets、文件等&#xff09;&#xff0c;并在其中任何一个文件描述符准备好进行I/O操作时进行处理。它的核心在于使用少量的线程或进程来管理多个I/O操作&#xff0c;以提…

【JavaSpring】spring接口-beanfactory和applicationcontext与事件解耦

beanfactory 1.applicationcontext的父接口 2.是Spring的核心容器 功能 表面只有getBean&#xff0c;但实现类默默发挥了巨大作用 1.管理所有bean 2.控制反转 3.基本的依赖注入 applicationcontext 功能 1.继承了MessageSource&#xff0c;有了处理国际化资源的能力 …

【C++】继承基础知识一遍过

目录 一&#xff0c;概念 二&#xff0c;继承定义 1. 继承格式 2. 访问限定符与继承方式的关系 3. 继承父类成员访问方式的变化 小结&#xff1a; 三. 父类与子类对象赋值转化 四&#xff0c;继承作用域 1.特点 2. 测试题 五&#xff0c;派生类不一样的默认成员函…

【nacos】2.1.1持续输出事件警告日志

nacos-server 2.1.1 持续输出事件警告日志,修复NamingTraceEvent连续打印日志。这是 2.1.1 beta 功能跟踪事件。如果没有订阅者处理TraceEvent&#xff0c;将打印此日志。2.1.1版本中忽略它&#xff0c;我们将在2.1.2版本中对其进行增强。 WARN There are no [com.alibaba.nac…

Linux系统中驱动之设备树的platform驱动实现

每日一个简单的驱动&#xff0c;日久方长&#xff0c;对Linux驱动就越来越熟悉&#xff0c;也越来容易学会写驱动程序。今日进行设备树下的platform设备驱动。 前面一篇我们讲解了传统的、未采用设备树的 platform 设备和驱动编写方法。最新的 Linux 内核已经支持了设备树&…

c语言练习45:模拟实现内存函数memcpy

模拟实现内存函数memcpy 针对内存块&#xff0c;不在乎内存中的数据。 拷贝内容有重叠的话应用memmove 模拟实现&#xff1a; 代码&#xff1a; 模拟实现memcpy #include<stdio.h> #include<assert.h> void* my_memcpy(void* dest, const void* src, size_t num…

【计算机基础知识3】IP 地址和子网掩码、DNS、HTTP

目录 前言 一、IP地址和子网掩码 1. IP地址的概念 2. IP地址的分类 3. 子网掩码的概念 4. 子网掩码的用途 二、域名系统&#xff08;DNS&#xff09; 1. DNS的作用 2. 域名解析过程 3. 如何配置和管理域名解析 三、HTTP&#xff08;超文本传输协议&#xff09; 1. H…

Pytest系列-测试用例前后置固件setup和teardown的介绍和使用(2)

简介 在unittest框架中&#xff0c;有两个前置方法&#xff0c;两个后置方法&#xff0c;还有两个模块方法&#xff0c;分别是 setup()&#xff1a;每个用例执行之前都会自动调用setupClass()&#xff1a;在类中所有的测试方法执行前会自动执行的代码&#xff0c;只执行一次t…

华为云中对象存储服务软件开发工具包(OBS SDK) C语言介绍

华为云的OBS介绍&#xff1a;摘自华为云官网&#xff1a;https://support.huaweicloud.com/obs/index.html 华为云的对象存储服务(Object Storage Service&#xff0c;OBS)是一个基于对象的海量存储服务&#xff0c;为客户提供海量、安全、高可靠、低成本的数据存储能力。 …

华为云云耀云服务器L实例评测|在Docker环境下部署Statping服务器监控工具

华为云云耀云服务器L实例评测&#xff5c;在Docker环境下部署Statping服务器监控工具 一、前言1.1 云耀云服务器L实例简介1.2 Statping简介1.3 Statping特点 二、本次实践介绍2.1 本次实践简介2.2 本次环境规划 三、购买云耀云服务器L实例3.1 购买云耀云服务器L实例3.3 查看云耀…

商汤科技AGI这些年:上半场「基建」,下半场「变现」

【潮汐商业评论/原创】 纵观一次次科技革命引领的生产力变革&#xff0c;都绝非一蹴而就&#xff0c;而是在不断的技术突破中&#xff0c;找到产业的落脚点&#xff0c;再回归到社会应用中去。 当下的人工智能也是如此。今年以来&#xff0c;大模型和生成式AI作为重要的科技突…

OpenCV项目实战(1)— 如何去截取视频中的帧

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。针对一段视频&#xff0c;如何去截取视频中的帧呢&#xff1f;本节课就给大家介绍两种方式&#xff0c;一种方式是按一定间隔来截取视频帧&#xff0c;另一种方式是截取视频的所有帧。希望大家学习之后能够有所收获&#x…