IOC容器创建bean实例的4种方式

🎈个人公众号:🎈 :✨✨✨ 可为编程✨ 🍟🍟
🔑个人信条:🔑 知足知不足 有为有不为 为与不为皆为可为🌵
🍉本篇简介:🍉 本篇记录IOC容器创建bean实例的4种方式,如有出入还望指正。

关注公众号【可为编程】回复【面试】领取年度最新面试题!!!

了解了IOC是什么,接下来我们看IOC容器能做什么,首先其最最主要的功能就是对Bean进行管理和创建,IOC容器创建bean实例共有4种方式,具体如下:

  1. 通过反射调用构造方法创建bean对象

  2. 通过静态工厂方法创建bean对象

  3. 通过实例工厂方法创建bean对象

  4. 通过FactoryBean创建bean对象

Spring容器内部创建bean实例对象常见的有4种方式,这四种又可以分为两大种,一是基于反射机制,二是基于工厂模式,我将基于此并结合案例深入说明一下两者的区别和原理。

1、通过反射调用构造方法创建bean对象

调用类的构造方法获取对应的bean实例,是使用最多的方式,这种方式只需要在xml bean元素中指定class属性,spring容器内部会自动调用该类型的构造方法来创建bean对象,将其放在容器中以供使用。

如果是采用注解形式创建和管理Bean,同样也是采用反射的机制,随着Spring的发展,注解(Annotation)逐渐成为主流的配置方式。使用注解可以减少配置文件的代码量,并且把相关的配置信息和代码放在一起,提高了可维护性。例如,使用@Component、@Service、@Repository、@Controller等注解可以自动创建Bean。

关注公众号【可为编程】回复【面试】领取年度最新面试题大全!!!

<bean id="bean名称" name="bean名称或者别名" class="bean的完整类型名称">
<constructor-arg index="0" value="bean的值" ref="引用的bean名称" />
<constructor-arg index="1" value="bean的值" ref="引用的bean名称" />
....
<constructor-arg index="n" value="bean的值" ref="引用的bean名称" />
</bean>

constructor-arg用于指定构造方法参数的值

index:构造方法中参数的位置,从0开始,依次递增

value:指定参数的值

ref:当插入的值为容器内其他bean的时候,这个值为容器中对应bean的名称

举个例子:这里我采用两种方式,首先采用Xml配置文件形配置并式定义Bean,二是采用注解形式生成Bean。

2、 IOC容器初始化细节

Person类
public class Person {

    public String name;
    public Integer age;
    Wife wife;

    public Person(String s, Integer s2, Wife wife) {
        System.out.println("反射通过调用构造函数进行实例创建...");
        this.name = s;
        this.age = s2;
        this.wife = wife;
    }
...省略属性的get() set()方法
}

beans.xml配置

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

    <!--构造方法中增加妻子对象-->
    <bean class="org.kewei.pojo.Person" id="person">
        <constructor-arg type="org.kewei.pojo.Wife" ref="wife"/>
        <constructor-arg index="0" value="可为编程" />
        <constructor-arg index="1" value="18" />
    </bean>
    <bean class="org.kewei.pojo.Wife" id="wife" autowire-candidate="true">
        <property name="age" value="18"/>
        <property name="name" value="可为"/>
    </bean>

</beans>

spring容器创建Person的时候,会通过反射的方式去调用Person类中对应的构造函数来创建Person对象。

public class Main {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("test.xml");
        Person person = (Person) classPathXmlApplicationContext.getBean("person");
        System.out.println(person.name+person.age);
        System.out.println(person.getWifeName() + person.getWifeAge());
    }
}

采用注解@Service定义Bean,如果没有指定BeanId,系统会自动以类名的首字母小写作为Bean名称进行生成。 

@Service
public class KeWeiService {
    public KeWeiService() {

        System.out.println("基于注解形式创建正在创建KeWeiService---   " + this);
        System.out.println("反射通过调用构造函数进行实例创建...---   " + this);
    }
}
//获取Bean
public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(KeWeiService.class);
        KeWeiService kw = (KeWeiService) annotationConfigApplicationContext.getBean("keWeiService");
        System.out.println(kw);
    }
}

测试结果如下所示,可见都是采用了反射的机制进行Bean的生成创建。只不过两种不同的方式,根本原理上来说还是基于Java的反射原理。

图片

Spring框架在创建Bean时,使用了Java反射(Reflection)机制。这种机制允许Spring在运行时检查和修改对象的一些行为。比如AOP就是采用了反射机制,对Bean可以在运行时对其进行行为修改,比如切面(Aspect),可以拦截目标对象的方法调用,并在调用前后加入额外的逻辑处理,Spring使用反射获取目标方法的信息,并动态地织入额外的代码逻辑。诚然,这块也用到了动态代理技术。

关注公众号【可为编程】回复【面试】领取年度最新面试题大全!!!

总之,Spring容器使用反射来实例化、配置和管理Bean。当Spring容器启动时,它会读取配置文件(例如XML或Java类注释),并根据这些配置信息创建Bean实例。在这个过程中,Spring使用反射来调用对象的构造函数或静态方法来创建Bean,对于属性,Spring还使用反射来设置Bean的属性,当配置文件中定义了一个Bean的属性时,Spring会使用反射调用对象的setter方法来设置这些Bean的属性值。其实反射在Spring的很多地方都有体现,利用Java反射机制Spring实现了延迟加载、依赖注入以及AOP等核心功能。

2、 通过静态工厂方法创建Bean对象

我们还可以采用工厂模式,创建静态工厂,内部提供一些静态方法来生成所需要的对象,将这些静态方法创建的对象交给spring以供后续使用。

<bean id="bean名称" name="" class="静态工厂完整类名" factory-method="静态工厂的方法">
    <constructor-arg index="0" value="bean的值" ref="引用的bean名称" />
    <constructor-arg index="1" value="bean的值" ref="引用的bean名称" />
    ....
    <constructor-arg index="n" value="bean的值" ref="引用的bean名称" />
</bean>

class:指定静态工厂完整的类名

factory-method:静态工厂中的静态方法,返回需要的对象。

constructor-arg用于指定静态方法参数的值,用法和上面介绍的构造方法一样。

spring容器会自动调用静态工厂的静态方法获取指定的对象,将其放在容器中以供使用。

定义静态工厂

创建一个静态工厂类,用于生成Person对象。

public class PersonStaticFactory {

    /**
     * 静态无参方法创建Person
     *
     * @return
     */
    public static Person build() {
        System.out.println(PersonStaticFactory.class + ".buildPerson1()");
        Person person = new Person();
        person.setName("我是无参静态构造方法创建的!");
        return person;
    }

    /**
     * 静态有参方法创建Person
     *
     * @param name 名称
     * @param age  年龄
     * @return
     */
    public static Person build2(String name, int age) {
        System.out.println(PersonStaticFactory.class + ".buildPerson2()");
        Person person2 = new Person();
        person2.setName(name);
        person2.setAge(age);
        return person2;
    }
}
beans.xml配置
<!-- 通过工厂静态无参方法创建bean对象 -->
<bean id="createBeanByStaticFactoryMethod1" class="org.kewei.service.PersonStaticFactory"
factory-method="build"/>
<!-- 通过工厂静态有参方法创建bean对象 -->
<bean id="createBeanByStaticFactoryMethod2" class="org.kewei.service.PersonStaticFactory"
factory-method="build2">
   <constructor-arg index="0" value="通过工厂静态有参方法创建UerModel实例对象"/>
   <constructor-arg index="1" value="30"/>
</bean>

上面配置中,spring容器启动的时候会自动调用PersonStaticFactory中的build()静态方法获取Person对象,将其作为createBeanByStaticFactoryMethod1名称对应的bean对象放在IOC容器当中。

调用PersonStaticFactory的build2()方法,并且会传入2个指定的参数,得到返回的Person对象,将其作为createBeanByStaticFactoryMethod2名称对应的bean对象放在IOC容器中。

ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("test.xml");
Person createBeanByStaticFactoryMethod1 = (Person) classPathXmlApplicationContext.getBean("createBeanByStaticFactoryMethod1");
Person createBeanByStaticFactoryMethod2 = (Person) classPathXmlApplicationContext.getBean("createBeanByStaticFactoryMethod2");
System.out.println(createBeanByStaticFactoryMethod1.name+createBeanByStaticFactoryMethod1.age);
System.out.println(createBeanByStaticFactoryMethod2.name+createBeanByStaticFactoryMethod2.age);
---------------------------------------------
我是无参静态构造方法创建的!null
通过工厂静态有参方法创建Person实例对象30

从输出中可以看出,两个静态方法都被调用了,都输出了对应的信息,第一行为build()方法生成的Bean,第二行为build2()方法生成的Bean对象。

上面是通过配置文件的形式获取Bean对象,接下来我再演示一下通过注解的方式如何通过静态工厂生成Bean对象。

关注公众号【可为编程】回复【面试】领取年度最新面试题大全!!!

注解配置

当然,方法是静态的我们就可以直接调用,但为了演示注解的作用,交给Spring做管理,因此我们通过加注解的形式,获取Bean对象。

@Configuration
public class PersonStaticFactory {

    /**
     * 静态无参方法创建Person
     *
     * @return
     */
    @Bean("createBeanByStaticFactoryMethod1")
    public static Person build() {
        System.out.println(PersonStaticFactory.class + ".buildPerson1()");
        Person person = new Person();
        person.setName("我是无参静态构造方法创建的!");
        return person;
    }

    /**
     * 静态有参方法创建Person
     *
     * @return
     */
    @Bean("createBeanByStaticFactoryMethod2")
    public static Person build2() {
        System.out.println(PersonStaticFactory.class + ".buildPerson2()");
        Person person2 = new Person();
        person2.setName("通过工厂静态有参方法创建");
        person2.setAge(18);
        return person2;
    }
}

通过@Bean注解使用一个静态方法创建一个Bean,并通过Bean的名称(在这里是createBeanByStaticFactoryMethod1)来获取它。首先要保障配置类被Spring扫描到使用@Configuration注解来标记配置类。在非Spring管理的类中直接通过名称获取Bean,需要手动从Spring上下文AnnotationConfigApplicationContext中获取它。

AnnotationConfigApplicationContext annotationConfigApplicationContext1 = new AnnotationConfigApplicationContext(PersonStaticFactory.class);
Person createBeanByStaticFactoryMethod1 = (Person) annotationConfigApplicationContext1.getBean("createBeanByStaticFactoryMethod1");
Person createBeanByStaticFactoryMethod2 = (Person) annotationConfigApplicationContext1.getBean("createBeanByStaticFactoryMethod2");
System.out.println(createBeanByStaticFactoryMethod1.name+createBeanByStaticFactoryMethod1.age);
System.out.println(createBeanByStaticFactoryMethod2.name+createBeanByStaticFactoryMethod2.age);

很显然,比我们用Xml配置的形式,少了好多代码,这也是Spring后期推行的主流方式。

3、通过实例工厂方法创建bean对象

让spring容器去调用某些对象的某些实例方法来生成bean对象放在容器中以供使用。

<bean id="bean名称" factory-bean="需要调用的实例对象bean名称" factory-method="bean对象中的方法">
    <constructor-arg index="0" value="bean的值" ref="引用的bean名称" />
    <constructor-arg index="1" value="bean的值" ref="引用的bean名称" />
    ....
    <constructor-arg index="n" value="bean的值" ref="引用的bean名称" />
</bean>

spring容器以factory-bean的值为bean名称查找对应的bean对象,然后调用该对象中factory-method属性值指定的方法,将这个方法返回的对象作为当前bean对象放在容器中供使用。

定义一个实例工厂

内部写2个方法用来创建Person对象。

public class PersonFactory {

    /**
     * 静态无参方法创建Person
     *
     * @return
     */
    public Person build() {
        System.out.println(PersonFactory.class + ".buildPerson1()");
        Person person = new Person();
        person.setName("我是无参静态构造方法创建的!");
        return person;
    }

    /**
     * 静态有参方法创建Person
     * 关注公众号【可为编程】回复【面试】领取年度最新面试题大全!!!
     *
     * @return
     */
    public Person build2(String name, int age) {
        System.out.println(PersonFactory.class + ".buildPerson2()");
        Person person2 = new Person();
        person2.setName(name);
        person2.setAge(age);
        return person2;
    }
}
beans.xml配置
  <!-- 定义一个工厂实例 -->
  <bean id="personFactory" class="org.kewei.service.PersonFactory"/>
  <!-- 通过userFactory实例的无参user方法创建UserModel对象 -->
  <bean id="createBeanByBeanMethod1" factory-bean="personFactory" factory-method="build"/>
  <!-- 通过userFactory实例的有参user方法创建UserModel对象 -->
  <bean id="createBeanByBeanMethod2" factory-bean="personFactory" factory-method="build2">
      <constructor-arg index="0" value="通过bean实例有参方法创建UserModel实例对象"/>
      <constructor-arg index="1" value="30"/>
  </bean>

createBeanByBeanMethod1对应的bean是通过personFactory的build方法生成的。

createBeanByBeanMethod2对应的bean是通过personFactory的build2方法生成的。

ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("test.xml");
Person createBeanByStaticFactoryMethod1 = (Person) classPathXmlApplicationContext.getBean("createBeanByBeanMethod1");
Person createBeanByStaticFactoryMethod2 = (Person) classPathXmlApplicationContext.getBean("createBeanByBeanMethod2");
System.out.println(createBeanByStaticFactoryMethod1.name+createBeanByStaticFactoryMethod1.age);
System.out.println(createBeanByStaticFactoryMethod2.name+createBeanByStaticFactoryMethod2.age);
---------------------------------------------
我是无参静态构造方法创建的!null
通过bean实例有参方法创建UserModel实例对象30

同样我们可以改成注解的形式

注解配置
@Service
public class PersonFactory {

    /**
     * 静态无参方法创建Person
     *
     * @return
     */
    public Person build() {
        System.out.println(PersonFactory.class + ".buildPerson1()");
        Person person = new Person();
        person.setName("我是无参静态构造方法创建的!");
        return person;
    }

    /**
     * 静态有参方法创建Person
     *
     * @return
     */
    public Person build2(String name, int age) {
        System.out.println(PersonFactory.class + ".buildPerson2()");
        Person person2 = new Person();
        person2.setName(name);
        person2.setAge(age);
        return person2;
    }
}

我们只需要在上面加一个@Service注解,就可以直接调用里面的方法。

 AnnotationConfigApplicationContext annotationConfigApplicationContext1 = new AnnotationConfigApplicationContext(PersonFactory.class);
 PersonFactory personFactory = (PersonFactory) annotationConfigApplicationContext1.getBean("personFactory");
 System.out.println(personFactory.build().name);
---------------------------------------------
class org.kewei.service.PersonFactory.buildPerson1()
我是无参静态构造方法创建的!

4、通过FactoryBean来创建bean对象

前面我们学过了BeanFactory接口,BeanFactory是Spring容器的顶层接口,而这里要说的是FactoryBean,也是一个接口,这两个接口很容易搞混淆,FactoryBean可以让Spring容器通过这个接口的实现来创建我们需要的bean对象。

关注公众号【可为编程】回复【面试】领取年度最新面试题大全!!!

FactoryBean接口源码:

public interface FactoryBean<T> {
    /**
     * 返回创建好的对象
     */
    @Nullable
    T getObject() throws Exception;
    /**
     * 返回需要创建的对象的类型
     */
    @Nullable
    Class<?> getObjectType();
    /**
    * bean是否是单例的
    **/
    default boolean isSingleton() {
        return true;
    }
}

接口中有3个方法,前面2个方法需要我们去实现,getObject方法内部由开发者自己去实现对象的创建,然后将创建好的对象返回给Spring容器;getObjectType需要指定我们创建的bean的类型;最后一个方法isSingleton表示通过这个接口创建的对象是否是单例的,如果返回false,那么每次从容器中获取对象的时候都会调用这个接口的getObject() 去生成bean对象。

<bean id="bean名称" class="FactoryBean接口实现类" />
创建一个FactoryBean实现类​​​​​​​
public class PersonFactoryBean implements FactoryBean<Person> {
    int count = 1;

    @Nullable
    @Override
    public Person getObject() { //1
        Person person = new Person();
        person.setName("我是通过FactoryBean创建的第" + count++ + "对象");//4
        return person;
    }

    @Nullable
    @Override
    public Class<?> getObjectType() {
        return Person.class; //2
    }

    @Override
    public boolean isSingleton() {
        return true; //3
    }
}

//1:返回了一个创建好的Person对象。

//2:返回对象的Class对象。

//3:返回true,表示创建的对象是单例的,那么我们每次从容器中获取这个对象的时候都是同一个对象。

//4:此处用到了一个count,通过这个一会可以看出isSingleton不同返回值的时候从容器获取的bean是否是同一个。

bean xml配置
<!-- 通过FactoryBean 创建Person对象 -->

<bean id="createByFactoryBean" class="org.kewei.service.PersonFactoryBean"/>

启动类增加如下代码:

System.out.println("-------------以下是FactoryBean创建的Bean对象-------------");
//1.bean配置文件位置
String beanXml = "classpath:/test.xml";
//2.创建ClassPathXmlApplicationContext容器,给容器指定需要加载的bean配置文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(beanXml);
System.out.println("spring容器中所有bean如下:");
//getBeanDefinitionNames用于获取容器中所有bean的名称
//关注公众号【可为编程】回复【面试】领取年度最新面试题大全!!!
for (String beanName : context.getBeanDefinitionNames()) {
     System.out.println(beanName + ":" + context.getBean(beanName));
}
//多次获取createByFactoryBean看看是否是同一个对象
System.out.println("createByFactoryBean:" + context.getBean("createByFactoryBean"));
System.out.println("createByFactoryBean:" + context.getBean("createByFactoryBean"));

图片

注意最后3行输出,输出的都是同一个createByFactoryBean,并且对象唯一,程序中通过getBean从IOC容器中查找createByFactoryBean3次,3次结果都是相同对象,说明返回的都是同一个Person对象。

下面我们将UserFactoryBean中的isSingleton调整一下,返回false

@Override

public boolean isSingleton() {

return false;

}

当这个方法返回false的时候,表示由这个FactoryBean创建的对象是多例的,那么我们每次从容器中getBean的时候都会去重新调用FactoryBean中的getObject方法获取一个新的对象,再运行一下Client,最后3行输出:

图片

很明显这3次获取的对象不一样,这也是SpringBean的作用域不同,下一篇进行讲解SpringBean的作用域。

总结

SpringIOC容器提供了4种创建bean实例的方式,除了构造函数的方式,其他几种方式可以让我们手动去控制对象的创建,这几种方式大家都掌握一下,能够灵活使用。需要源码的联系我获取。

图片

由表及里分析Spring-IOC容器始末

Spring中的核心概念

不要称之为卷土重来:为什么 Java 仍然会是冠军!

关于高并发你必须知道的几个概念

线程的创建方式对比与线程池相关原理剖析

BigDecimal对象的日常使用汇总

图片

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

关于 HTML 的一切:初学者指南

HTML 代表超文本标记语言&#xff0c;是用于创建网页和 Web 应用程序的标准语言。 本指南将全面介绍 HTML&#xff0c;涵盖从基本语法和语义到更高级功能的所有内容。 我的目标是用简单的术语解释 HTML&#xff0c;以便即使没有编码经验的人也能学习如何使用 HTML 构建网页。…

PostCSS通过px2rem插件和lib-flexible将px单位转换为rem(root em)单位实现大屏适配

目录 文档postcss中使用postcss-plugin-px2rem安装postcss-plugin-px2rem示例默认配置 webpack中使用postcss-plugin-px2rem项目结构安装依赖文件内容 大屏适配参考文章 文档 类似的插件 postcss-plugin-px2rem https://www.npmjs.com/package/postcss-plugin-px2remhttps://g…

Go invalid memory address or nil pointer dereference错误 空指针问题

Go 指针声明后赋值&#xff0c;出现 panic: runtime error: invalid memory address or nil pointer dereference&#xff0c;这种是内存地址错误。 首先我们要了解指针&#xff0c;指针地址在 Go 中 * 代表取指针地址中存的值&#xff0c;& 代表取一个值的地址对于指针&am…

JVM 各个参数详解

在一些规模稍大的应用中&#xff0c;Java虚拟机&#xff08;JVM&#xff09;的内存设置尤为重要&#xff0c;想在项目中取得好的效率&#xff0c;GC&#xff08;垃圾回收&#xff09;的设置是第一步。 PermGen space&#xff1a;全称是Permanent Generation space.就是说是永久…

PDF文件解析

一、PDF文件介绍 PDF是英文Portable Document Format缩写&#xff0c;就是可移植的意思&#xff0c;它是以PostScript语言图象模型为基础&#xff0c;无论在哪种打印机上都可保证精确的颜色和准确的打印效果&#xff0c;PostScript咱也不懂&#xff0c;估计和SVG的原理差不多吧…

k8s提交spark应用消费kafka数据写入elasticsearch7

一、k8s集群环境 k8s 1.23版本&#xff0c;三个节点&#xff0c;容器运行时使用docker。 spark版本时3.3.3 k8s部署单节点的zookeeper、kafka、elasticsearch7 二、spark源码 https://download.csdn.net/download/TT1024167802/88509398 命令行提交方式 /opt/module/spark…

14:00面试,14:06就出来了,问的问题有点变态。。。。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到5月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…

pytorch3D Windows下安装经验总结

一、说明及准备工作 最近在安装pytorch3D的时候遇到了很多问题&#xff0c;查了很多博客&#xff0c;但发现讲的都不太全&#xff0c;所以特将自己的及收集到的安装过程经验总结如下。我是在Anaconda中虚拟环境下安装的。 1.1准备工作 官方安装教程如下&#xff1a;https://…

Docker Tomcat 搭建文件服务器

本文基于openwrt上进行。 步骤 1: 安装 Docker 如果尚未安装Docker&#xff0c;首先需要安装Docker。根据你的操作系统&#xff0c;参考Docker官方文档来完成安装, 这里不做详细介绍。 步骤 2: 拉去docker Tomcat镜像 进入openwrt管理界面&#xff0c;docker选项中 拉取最新…

Java 设计模式——外观模式

目录 1.概述2.结构3.实现3.1.子系统类3.2.外观类3.3.测试 4.优缺点5.使用场景6.源码解析 1.概述 &#xff08;1&#xff09;有些人可能炒过股票&#xff0c;但其实大部分人都不太懂&#xff0c;这种没有足够了解证券知识的情况下做股票是很容易亏钱的&#xff0c;刚开始炒股肯…

Zeus IoT : 基于 SpringBoot 的分布式开源物联网大数据平台

Zeus IoT 是一个集设备数据采集、存储、分析、观测为一体的开源物联网平台&#xff0c;全球首创基于 Zabbix 的物联网分布式数据采集架构&#xff0c;具备超百万级物联网设备的并发监控能力&#xff0c;真正具备工业级性能与稳定性的开源物联网大数据中台。 Zeus IoT 致力于让设…

Zinx框架-游戏服务器开发002:框架学习-按照三层结构模式重构测试代码+Tcp数据适配+时间轮定时器

文章目录 1 Zinx框架总览2 三层模式的分析3 三层重构原有的功能 - 头文件3.1 通道层Stdin和Stdout类3.1.2 StdInChannel3.1.2 StdOutChannel 3.2 协议层CmdCheck和CmdMsg类3.2.1 CmdCheck单例模式3.2.1.1 单例模式3.2.1.2 * 命令识别类向业务层不同类别做分发 3.2.2 CmdMsg自定…

Node.js |(五)包管理工具 | 尚硅谷2023版Node.js零基础视频教程

学习视频&#xff1a;尚硅谷2023版Node.js零基础视频教程&#xff0c;nodejs新手到高手 文章目录 &#x1f4da;概念介绍&#x1f4da;npm&#x1f407;安装npm&#x1f407;基本使用&#x1f407;生产依赖与开发依赖&#x1f407;npm全局安装&#x1f407;npm安装指定包和删除…

4、Python基本数据类型:数字、字符串、列表、元组、集合、字典

文章目录 1、Python基本数据类型简介2、数字3、字符串4、列表5、元组6、集合7、字典1、Python基本数据类型简介 Python是一种非常强大且易于学习的编程语言,它具有简洁的语法和丰富的数据类型。了解和掌握Python的基本数据类型是学习和使用Python的基础。本文将详细介绍Pytho…

Disk Drill v5.3.1313(数据恢复备份)

Disk Drill是一款功能强大的数据恢复软件&#xff0c;它可以帮助用户恢复已删除、丢失、格式化或损坏的文件&#xff0c;并支持多种存储设备&#xff0c;包括计算机硬盘驱动器、外部硬盘、USB闪存驱动器、内存卡和其他存储介质。它和很多的文件系统都兼容&#xff0c;比如&…

nodejs express uniapp 图书借阅管理系统源码

开发环境及工具&#xff1a; nodejs&#xff0c;mysql5.7&#xff0c;HBuilder X&#xff0c;vscode&#xff08;webstorm&#xff09; 技术说明&#xff1a; nodejs express vue elementui uniapp 功能介绍&#xff1a; 用户端&#xff1a; 登录注册 首页显示轮播图&am…

排序算法的分析及实现

目录​​​​​​​ 1. 排序 1.1. 排序的概念 1.2. 排序的稳定性 1.3. 内部排序和外部排序 2. 直接插入排序 2.1. 直接插入排序 2.2. 直接插入排序的两种情况 1. 情况一 2. 情况二 2.3. 直接插入排序的单趟排序 2.4. 直接插入排序的完整实现 2.5. 直接插入排序的时…

【江协科技-用0.96寸OLED播放知名艺人打篮球视频】

Python进行视频图像处理&#xff0c;通过串口发送给stm32&#xff0c;stm32接收数据&#xff0c;刷新OLED进行显示。 步骤&#xff1a; 1.按照接线图连接好硬件 2.把Keil工程的代码下载到STM32中 3.运行Python代码&#xff0c;通过串口把处理后的数据发送给STM32进行显示 …

【图像分类】【深度学习】【Pytorch版本】AlexNet模型算法详解

【图像分类】【深度学习】【Pytorch版本】AlexNet模型算法详解 文章目录 【图像分类】【深度学习】【Pytorch版本】AlexNet模型算法详解前言AlexNet讲解卷积层的作用卷积过程特征图的大小计算公式Dropout的作用AlexNet模型结构 AlexNet Pytorch代码完整代码总结 前言 AlexNet是…

论文阅读——What Can Human Sketches Do for Object Detection?(cvpr2023)

论文&#xff1a;https://openaccess.thecvf.com/content/CVPR2023/papers/Chowdhury_What_Can_Human_Sketches_Do_for_Object_Detection_CVPR_2023_paper.pdf 代码&#xff1a;What Can Human Sketches Do for Object Detection? (pinakinathc.me) 一、 Baseline SBIR Fram…