Spring的自动注入(也称为自动装配)

自动注入(也称为自动装配)是Spring框架中的一个核心概念,它与手动装配相对立,提供了一种更简洁、更灵活的方式来管理Bean之间的依赖关系。

在Spring应用程序中,如果类A依赖于类B,通常需要在类A中定义一个类型为B的属性,并提供相应的setter方法。然而,在自动注入的上下文中,我们无需在XML配置文件中显式地描述这两个类之间的依赖关系。当Spring容器启动时,它会根据配置自动实例化bean。在实例化类A的过程中,Spring容器会检查类A的属性,并尝试自动装配这些属性。由于Spring容器能够识别类A依赖于类B(通过反射或其他机制),它会自动将合适的类B的实例注入到类A的对应属性中。这种由Spring容器自动处理依赖关系的方式称为自动注入。

而与之相对的是手动装配,即程序员在XML配置文件中显式地指定bean之间的依赖关系。在手动装配中,程序员需要明确告诉Spring容器哪些bean应该被注入到哪些属性中。

总结来说,自动注入是Spring框架提供的一种简化依赖管理的机制,它通过自动解析bean之间的依赖关系来减少手动配置的工作量。而手动装配则需要程序员在配置文件中显式地指定依赖关系,如下:

在这里插入图片描述

package com.zhaoshu.xmlioc;
import com.zhaoshu.di.A;
import com.zhaoshu.xmlioc.service.UserService;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Test {@org.junit.jupiter.api.Testvoid testdi() {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");A a = (A) context.getBean("a");a.print();}
}

但是实际开发中手动装配的场景比较少(比如在缺少源码的情况下可能会使用这种手动装配情况)。

在Spring框架中,依赖注入(DI)是实现控制反转(IOC)的重要手段,它允许对象在运行时从外部源接收其依赖项,而不是通过硬编码或构造函数参数来创建它们。DI主要有两种主要的实现方式:基于构造方法的依赖注入和基于setter方法的依赖注入。然而,这两种方式并不是唯一的,它们还有各自的变体形式。

首先,基于构造方法的依赖注入是一种常见的方式,它要求将依赖项作为参数传递给被依赖对象的构造函数。这种方式确保了依赖项在对象创建时就被注入,从而确保了对象的完整性和不变性。其次,基于setter方法的依赖注入则允许在对象创建后的某个时间点注入依赖项。它通过在对象上调用setter方法来设置依赖项的值。这种方式提供了更大的灵活性,因为可以在对象的不同生命周期阶段注入不同的依赖项。

除了这两种主要方式外,Spring还支持其他变体形式的依赖注入。例如,通过在类的属性上使用@Autowired注解,Spring可以利用Java的反射机制自动注入依赖项。这种方式可以视为setter注入方式的一种变体,因为它同样是在对象创建后注入依赖项,但无需显式调用setter方法。

在Spring中,无论是手动装配还是自动装配,本质上都是基于上述主要和变体形式的依赖注入方式来实现的。手动装配通常涉及在XML配置文件中显式地指定bean之间的依赖关系,而自动装配则通过Spring的自动检测机制自动解析bean之间的依赖关系,并在需要时注入依赖项。

在Spring框架中,当我们说“基于setter的注入”时,我们通常意味着依赖是通过一个特定的setter方法来注入的,这个setter方法通常会与类的某个私有属性相对应。但是,从Spring容器的角度来看,它并不关心这个setter方法是否确实对应了一个私有属性。在Spring的setter注入中,setter方法的存在仅仅是为了给Spring容器一个“钩子”,让容器可以在创建bean的实例时通过这个方法注入依赖。
在这里插入图片描述

因此,你可以说在Spring的setter注入中,setter方法本身并不直接依赖于类的某个私有属性。setter方法只是一个接口,允许Spring容器在创建bean时注入依赖。当然,在实际应用中,你通常会在类内部使用私有属性来保存这些依赖,以便在类的其他方法中使用它们。但这不是Spring容器所关心的,它只关心setter方法的存在和签名。

可能有的读者会认为上面的xml配置文件中已经手动装配了B给A,肯定会调用setXxx方法,其实不然,即是我使用自动装配也还是会调用的。笔者改一下代码,把A的注入模型改成自动注入来看看结果:

在这里插入图片描述

把代码改成上面这样自动装配结果是一样的,A类当中的setXxx方法还是会调用,不需要提供任何属性,可能有读者会说如果使用注解呢?比如如下代码:
在这里插入图片描述

上面代码同样会注入b,但是是调用反射机制去完成注入的,不是通过setter,当然再次说明一下这是setter的一种变体;上面代码直到A完成注入B后setter方法也不会调用。

重点来了!!!笔者看过很多资料说@Autowired也算自动装配,关于这点笔者不敢苟同,在一个属性上面加@Autowired注解应该属于手动装配,我会通过大量源码和例子来证明笔者的这个理论。

@Autowired注解被理解为自动装配的原因,主要是因为其基于类型的自动装配机制。以下是关于@Autowired和自动装配的详细解释:

  1. 自动装配的定义:
  • 在Spring框架中,自动装配是指Spring容器能够自动满足bean之间的依赖关系,而无需在配置文件中显式指定。
  1. @Autowired的作用:
  • @Autowired是Spring框架提供的一个注解,用于自动装配bean。它可以标注在成员变量、构造器或setter方法上,指示Spring容器自动查找并注入依赖的bean。
  1. 基于类型的自动装配:
  • @Autowired默认采用基于类型的自动装配。当Spring容器在创建一个bean时,会检查该bean中所有被@Autowired标注的字段、构造器参数或方法参数,并在Spring容器中查找与这些字段、参数类型相匹配的bean。
  • 如果Spring容器中只有一个与所需类型匹配的bean,那么Spring会自动将其注入到相应的字段或方法中。
  • 如果有多个与所需类型匹配的bean,Spring会抛出一个异常,除非使用其他机制(如@Qualifier注解)来指定要注入的bean。
  1. 其他机制:
  • 除了基于类型的自动装配外,Spring还支持基于名称的自动装配(例如使用@Resource注解)。但@Autowired主要是基于类型的。
  • @Autowired还可以与@Qualifier注解一起使用,以指定在多个相同类型bean存在时应该注入哪个bean。
  1. 代码示例:

@Autowired 是 Spring 框架中用于自动装配(Autowiring)的一个核心注解。它允许 Spring 容器自动解析和注入依赖项,而无需使用 XML 配置文件进行显式配置。下面我将通过几个例子来展示如何使用 @Autowired

  1. 成员变量上的 @Autowired

假设我们有两个类,一个是 UserService 类,它依赖于 UserRepository 类。

@Service
public class UserService {@Autowiredprivate UserRepository userRepository;// ... 其他方法和代码 ...public List<User> getAllUsers() {return userRepository.findAll();}
}@Repository
public interface UserRepository {List<User> findAll();// ... 其他方法 ...
}// 假设有一个实现类
@Repository
public class UserRepositoryImpl implements UserRepository {// 实现细节...
}

在这个例子中,UserService 类中的 userRepository 成员变量被 @Autowired 注解标记,这意味着 Spring 容器在创建 UserService 的实例时会自动查找一个 UserRepository 类型的 Bean 并将其注入到 userRepository 变量中。

  1. 构造器上的 @Autowired

从 Spring 4.3 开始,推荐在构造器上使用 @Autowired 来进行依赖注入。

@Service
public class UserService {private final UserRepository userRepository;@Autowiredpublic UserService(UserRepository userRepository) {this.userRepository = userRepository;}// ... 其他方法和代码 ...
}

在这个例子中,UserService 的构造器被 @Autowired 注解标记,这意味着 Spring 容器在创建 UserService 的实例时会自动调用这个构造器,并传入一个 UserRepository 类型的 Bean 作为参数。

  1. Setter 方法上的 @Autowired

虽然现在不太推荐使用 setter 方法进行自动装配(因为构造器注入提供了更好的不可变性和测试性),但下面是一个例子:

@Service
public class UserService {private UserRepository userRepository;@Autowiredpublic void setUserRepository(UserRepository userRepository) {this.userRepository = userRepository;}// ... 其他方法和代码 ...
}

在这个例子中,setUserRepository 方法被 @Autowired 注解标记,这意味着 Spring 容器在创建 UserService 的实例后会自动调用这个方法,并传入一个 UserRepository 类型的 Bean 作为参数。

注意事项:

  • 默认情况下,@Autowired 是按类型(byType)进行注入的。如果容器中存在多个相同类型的 Bean,你需要使用 @Qualifier 注解来指定要注入的 Bean 的名称。
  • 在使用 @Autowired 时,要确保你的类在 Spring 容器中是被管理的(即它们有 @Component@Service@Repository@Controller 等注解)。
  • 如果你的类中有多个构造函数或多个同名的 setter 方法,你需要明确指定哪个应该用于自动装配,否则可能会引发异常。

当你的类中有多个构造函数或多个同名的 setter 方法时,Spring 容器在尝试进行自动装配时可能会遇到困惑,因为它不知道应该使用哪个构造函数或 setter 方法来注入依赖。为了解决这个问题,你可以使用 @Autowired 注解明确指定要使用的构造函数或 setter 方法,或者使用 @Primary@Qualifier 注解来进一步区分 Bean。

  1. 多个构造函数

如果你有两个构造函数,并且都没有被 @Autowired 明确标记,Spring 容器将不知道在创建 Bean 时应该调用哪个构造函数。在这种情况下,通常最好只提供一个默认构造函数或者标记其中一个构造函数用于自动装配。

@Service
public class UserService {private final UserRepository userRepository;// 标记这个构造函数用于自动装配@Autowiredpublic UserService(UserRepository userRepository) {this.userRepository = userRepository;}// 另一个构造函数,可能用于其他目的(如测试)public UserService(UserRepository userRepository, AnotherDependency anotherDependency) {// 通常,这个构造函数不会被自动装配,除非你在某个地方明确指定了它}// ... 其他方法和代码 ...
}

在这个例子中,只有第一个构造函数被 @Autowired 标记,因此 Spring 容器在创建 UserService 的实例时会调用这个构造函数。

  1. 多个同名的 setter 方法

如果你的类中有多个同名的 setter 方法(这通常不会发生,因为 setter 方法通常遵循特定的命名约定,如 setFieldName),并且你试图使用 @Autowired 进行自动装配,Spring 容器同样会不知道应该调用哪个 setter 方法。但是,这种情况在实际开发中很少见,因为 setter 方法的命名通常是根据字段名生成的。

然而,如果你确实遇到了这种情况(可能是通过继承或其他方式),你可以使用 @Autowired 明确指定要使用的 setter 方法,或者使用 @Qualifier 来区分 Bean。但是,由于 setter 方法通常不会同名,因此这个问题通常不会出现。

  1. 使用 @Primary@Qualifier 解决歧义

当你有多个相同类型的 Bean 时,你可以使用 @Primary@Qualifier 来解决歧义。

  • @Primary:当存在多个相同类型的 Bean 时,标记其中一个 Bean 为首选 Bean。如果自动装配时发现多个匹配项,首选的 Bean 会被选中。
  • @Qualifier:在自动装配时,你可以使用 @Qualifier 注解明确指定要注入的 Bean 的名称。
@Repository
@Primary // 标记这个 Bean 为首选 Bean
public class PrimaryUserRepository implements UserRepository {// ... 实现细节 ...
}@Repository
public class SecondaryUserRepository implements UserRepository {// ... 实现细节 ...
}@Service
public class UserService {private UserRepository userRepository;@Autowired@Qualifier("secondaryUserRepository") // 明确指定要注入的 Bean 的名称public void setUserRepository(UserRepository userRepository) {this.userRepository = userRepository;}// ... 其他方法和代码 ...
}

在这个例子中,虽然有两个 UserRepository 类型的 Bean,但 UserService 中的 setUserRepository 方法使用 @Qualifier 注解明确指定了要注入的 Bean 的名称。同时,PrimaryUserRepository 被标记为首选 Bean,如果在其他地方没有指定特定的 Bean 名称,它将会被选中。

总结:

  • @Autowired注解之所以被理解为自动装配,是因为它能够根据字段、构造器参数或方法参数的类型,在Spring容器中自动查找并注入匹配的bean,从而实现了bean之间的自动装配。这种基于类型的自动装配机制是@Autowired注解的核心功能之一。

自动装配(Autowiring)的出现确实是为了解决手动装配时配置文件过于冗余和臃肿的问题。在Spring的早期版本中,开发者通常需要在XML配置文件中显式地定义每个bean以及它们之间的依赖关系,这对于复杂的应用程序来说可能会导致配置文件变得非常庞大和难以管理。Spring的自动装配功能通过减少配置文件中需要编写的代码量,来简化bean之间的依赖管理。它允许容器自动检测并满足bean之间的依赖关系,而无需在配置文件中显式地指定这些关系。

之所以会有人把@Autowired也理解为自动装配的原因是因为bytype引起的,因为spring官网有说明自动装配有四种模型分表是no、bytype、byname、constructor;现在流行着这么一种说法:@Autowired就是通过bytype来完成注入的。如果你也认为这种说法成立,那么就是默认了@Autowired是自动装配且装配模型是bytype。笔者见过很多程序员和很多资料都支持这种说法,其实严格意义上来讲这句话大错特错,甚至有误人子弟的嫌疑。因为bytype仅仅是一种自动注入模型而已,这种模型有其固有的技术手段,而@Autowired是一个注解,这个注解会被spring的后置处理器解析,和处理bytype不是同一回事。如果需要讲清楚他们的区别和证明@Autowired不是自动装配则首先要搞明白什么自动装配。笔者接下来会花一定篇幅来解释自动装配的知识,然后回过头来讲他们的区别和证明@Autowired属性手动装配。

如果现在已经理解了手动装配也叫手动注入,也已经理解了注入方式(setter和构造方法),那么接下来讨论自动注入或者叫自动装配;自动注入的出现是因为手动装配过于麻烦,比如某个类X当中依赖了10个其他类那么配置文件将会变的特别冗余和臃肿,spring的做法是可以为这个X类提供一种叫做自动装配的模型,无需程序员去手动配置X类的依赖关系。有读者会疑问,用注解不也是可以解决这个xml臃肿的问题?确实用注解可以解决,但是我们现在讨论的是自动装配的问题,就不能用注解;为什么不能用注解来讨论自动装配的问题呢?因为在不配置BeanFactoryPostProcessor和修改beanDefinition的情况下注解的类是不支持自动装配的(关于BeanFactoryPostProcessor和beanDefinition的知识笔者以后有时间更新);这也是证明@Autowired默认不是自动装配的一个证据,那又如何证明注解类是默认不支持自动装配呢?下文我会解释一个注解类默认是不支持自动装配的。也就是说如果讨论自动装配最好是用xml形式来配置spring容器才会有意义;比如下面这个例子:

在这里插入图片描述

上面代码运行起来,A能注入B,但是在xml配置文件中并没有去手动维护、描述他们之间的依赖关系,而是在xml的根标签上面写了一行default-autowire=“byType”,其实关于自动注入的歧义或者被人误解的地方就是这个default-autowire="byType"引起的;那么这行代码表示什么意思呢?表示所在配置在当前xml当中的bean都以bytype这种模式自动装配模式(如果没有特殊指定,因为bean还可以单独配置装配模式的);这需要注意笔者的措辞,笔者说的bytype这自动装配模式,是一种模式,这个不是笔者信口开河,因为在官网文档里面spring也是这么定义的。

自动注入模型和前面提到的依赖注入方式(setter和构造方法)是两回事,简而言之:依赖注入是一个过程,主要通过setter和构造方法以及一些变体的方式完成把对象依赖、填充,这个过程叫做依赖注入,不管手动装配还是自动装配都有这个过程;而自动装配模型是一种完成自动装配依赖的手段体现,每一种模型都使用了不同的技术去查找和填充bean;

从spring官网上面可以看到spring只提出了4中自动装配模型(严格意义上是三种、因为第一种是no,表示不使用自动装配、使用),这四个模型分别用一个整形来表示,存在spring的beanDefinition当中,任何一个类默认是no这个装配模型,也就是一个被注解的类默认的装配模型是no也就是手动装配;其中no用0来表示;bytype用2来表示;

如果某个类X,假设X的bean对应的beanDefinition当中的autowireMode=2则表示这个类X的自动装配模型为bytype;如果autowireMode=1则表示为byname装配模型;需要注意的是官网上面说的四种注入模型其中并没有我们熟悉的@Autowired;可能有读者会提出假设我在A类的某个属性上面加上@Autowired之后这个A类就会不会成了自动装配呢?@Autowired是不是会改变这个类A当中的autowireMode呢?我们可以写一个例子来证明一下:

在这里插入图片描述
在这里插入图片描述

接下来笔者验证一个通过注解配置的类加上@Autowried后的注入模型的值:

在这里插入图片描述

可以看到结果为0,说明这个A类不是自动装配,其实这已经能证明@Autowried不是自动装配了,但是还有更直接的证据证明他不是自动装配,就是通过spring源码当中处理@Autowried的代码可以看出,首先我们写一个bytype的例子看看spring如何处理的:

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"default-autowire="byType"><!--自动装配--><bean id="a" class="com.luban.app.A"></bean><bean id="b"  class="com.luban.app.B"></bean>
</beans>
A.java
public class A {B b;/*** 如果是自动装配需要提供setter* 或者提供构造方法*/public void setB(B b) {this.b = b;}
}B.java
public class B {
}

上面代码运行起来,调试spring源码当中的org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean方法,这个方法主要就是完成属性填充的,也就是大家说的注入:
在这里插入图片描述

可以看上图929行有一个判断,判断当前类的注入模式是否bynane或者bytype如果是其中一种则会进入930行代码执行自动装配的逻辑;因为当前代码我在xml当中配置了自动注入模型为bytype所以这里一定会进入,从上图debug的结果我们可以得知确实也进入了930行,那我们再看看@Autowried到底是否是一样的呢?
在这里插入图片描述

我们使用@Autowired注解去注入一个属性的时候spring在完成属性注入的过程中和自动注入(byname、bytype)的过程不同,spring注解跳过了那个判断,因为不成立,而是用后面的代码去完成属性注入;这也是能说明@Autowired不是自动装配的证据、更是直接打脸@Autowired是先bytype的这种说法;当然除了这个证据还有更加直接的证据,先看代码:
在这里插入图片描述

其实最关键的就是这行代码

if (ctors != null || mbd.getResolvedAutowireMode() ==AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args);
}

这里有个判断 首先判断 ctors != null 然后判断类的自动注入模型是不是等于AUTOWIRE_CONSTRUCTOR(3);分两种情况来分析:

  • 第一种情况:若我们预先设定了类的自动注入模式为通过构造函数(constructor)进行,那么相关的条件判断(采用逻辑或||操作符)将会因为至少有一个条件成立而整个if语句执行。然而,在当前的上下文中,这种情况并不适用,因为作者并未明确指定类A的自动注入模式为特定值(如数字3,这通常不是标准的自动注入模式标识)。根据提供的代码片段,我们可以观察到mbd.getResolvedAutowireMode()的返回值是0,这表示自动装配模式尚未被明确设置或默认为不进行自动装配(即autowireMode=0,对应于AutowireMode.NO)。这再次印证了,在没有明确指定的情况下,注解类默认不会启用自动注入模式。
  • 第二种情况:没有指定类的自动注入模型,笔者代码例子就是这种情况,那么spring会首先推断出构造方法,笔者A里面一个带参数的构造方法,所以再进行第一个判断ctors!=
    null的时候就已经成立了,于是也会进入。
  • 结论:在一个注解类里面提供了一个构造方法之所以能达到和自动注入的效果一样并不是因为这种方式就是自动装配,而是因为spring源码当中做了判断;使这种情况下调用的代码和自动装配调用的逻辑一下。但是有的读者会说那这样也能算自动装配啊,当然如果读者一定这么认为那么也无可厚非;

@Autowried到底和bytype有什么关系呢?为什么有资料会把他们联系在一起呢?

首先bytype是一种自动注入模型,spring会根据类型去查找一个符合条件的bean,如果没找到则不注入,程序也不会报错;如果找到多个spring也不报错,但是也不完成注入,让这个属性等于null,比如你有个接口I,提供两个实现I1和I2都存在容器当中,然后在A类当中去注入I,并且指定自动注入模型为bytype那么这个时候会找到两个符合条件的bean,spring就迷茫了,注入哪个呢?spring哪个都不注入直接让这个属性为null而且也不出异常;但是如果找到了一个那么注入的时候会调用setter,如果没有提供setter就不会。
在这里插入图片描述

spring会首先根据属性的类型去容器中找,如果没有找到在根据属性的名字找,找到了则注入,没有找到则异常,下图结果就是容器当中没有一个符合的类型和名字都不符合的则异常;
在这里插入图片描述
如果先根据类型找到了一个,那么直接注入,下图就是只有一个符合要求的类型能够完美注入;

在这里插入图片描述
如果先根据类型找到了多个,那么spring不会立马异常,而是根据名字再找去找,如果根据名字找到一个合理的则注入这个合理的,下图就是I1和I2都符合,但是spring最后却没有异常,是因为属性名字叫i1故而先类型在名字找到了合理的;

以后如果再听到@Autowried是bytype请你纠正他,bytype是一种自动注入模型;@Autowried是一个注解,两个人没有关系,一点关系都没有;@Autowried讲道理算是手动装配;那么一个注解的类到底能不能开启自动装配呢?答案是可以的,但是需要你对spring比较精通,以后笔者再更新;

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

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

相关文章

qt 一个可以拖拽的矩形

1.概要 2.代码 2.1 mycotrl.h #ifndef MYCOTRL_H #define MYCOTRL_H#include <QWidget> #include <QMouseEvent>class MyCotrl: public QWidget {Q_OBJECT public://MyCotrl();MyCotrl(QWidget *parent nullptr); protected:void paintEvent(QPaintEvent *even…

MySQL 死锁查询和解决死锁

来了来了来了&#xff01;客户现场又要骂街了&#xff0c;你们这是什么破系统怎么这么慢啊&#xff1f;&#xff01;&#xff1f;&#xff01; 今天遇到了mysql死锁&#xff0c;直接导致服务器CPU被PUA直接GUA了&#xff01; 别的先别管&#xff0c;先看哪里死锁&#xff0c;或…

【MySQL数据库】:MySQL视图特性

视图的概念 视图是一个虚拟表&#xff0c;其内容由查询定义&#xff0c;同真实的表一样&#xff0c;视图包含一系列带有名称的列和行数据。视图中的数据并不会单独存储在数据库中&#xff0c;其数据来自定义视图时查询所引用的表&#xff08;基表&#xff09;&#xff0c;在每…

[保姆级教程]uniapp实现底部导航栏

文章目录 前置准备工作安装HBuilder-X新建uniapp项目教程使用HBuilder-X启动uniapp项目教程 实现底部导航栏package.json中配置导航栏详细配置内容 前置准备工作 安装HBuilder-X 详细步骤可看上文》》 新建uniapp项目教程 详细步骤可看上文》》 使用HBuilder-X启动uniapp项…

vivado、vitis2022安装及其注意事项(省时、省空间)

1、下载 AMD官网-资源与支持-vivado ML开发者工具&#xff0c;或者vitis平台&#xff0c; 下载的时候有个官网推荐web安装&#xff0c;亲测这个耗时非常久&#xff0c;不建议使用&#xff0c;还是直接下载89G的安装包快。 注意&#xff1a;安装vitis平台会默认安装vivado&…

【Deep Learning】Self-Supervised Learning:自监督学习

自监督学习 本文基于清华大学《深度学习》第12节《Beyond Supervised Learning》的内容撰写&#xff0c;既是课堂笔记&#xff0c;亦是作者的一些理解。 在深度学习领域&#xff0c;传统的监督学习(Supervised Learning)的形式是给你输入 x x x和标签 y y y&#xff0c;你需要训…

树莓派4B_OpenCv学习笔记12:OpenCv颜色追踪_画出轨迹

今日继续学习树莓派4B 4G&#xff1a;&#xff08;Raspberry Pi&#xff0c;简称RPi或RasPi&#xff09; 本人所用树莓派4B 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: Opencv 版本是4.5.1&#xff1a; 今日尝试使用倒叙的方式来学习OpenCV颜色追踪&#xff0…

Claude 3.5 强势出击:解析最新AI模型的突破与应用

近年来&#xff0c;人工智能领域的发展迅猛&#xff0c;各大科技公司纷纷推出了自家的高级语言模型。在这场技术竞赛中&#xff0c;Anthropic的Claude系列模型凭借其强大的性能和创新的功能脱颖而出。最近&#xff0c;Anthropic发布了Claude 3.5 Sonnet模型&#xff0c;引起了广…

如何设置Excel单元格下拉列表

如何设置Excel单元格下拉列表 在Excel中设置单元格下拉列表可以提高数据输入的准确性和效率。以下是创建下拉列表的步骤&#xff1a; 使用数据验证设置下拉列表&#xff1a; 1. 选择单元格&#xff1a; 选择你想要设置下拉列表的单元格或单元格区域。 2. 打开数据验证&…

高斯算法的原理及其与常规求和方法的区别

高斯算法的原理 高斯算法的原理源于数学家卡尔弗里德里希高斯在他少年时期发现的一种求和方法。当时老师让学生们计算1到100的和&#xff0c;高斯发现了一种快速计算的方法。 高斯注意到&#xff0c;如果将序列的首尾两数相加&#xff0c;结果总是相同的。例如&#xff1a; …

DVWA 靶场 JavaScript 通关解析

前言 DVWA代表Damn Vulnerable Web Application&#xff0c;是一个用于学习和练习Web应用程序漏洞的开源漏洞应用程序。它被设计成一个易于安装和配置的漏洞应用程序&#xff0c;旨在帮助安全专业人员和爱好者了解和熟悉不同类型的Web应用程序漏洞。 DVWA提供了一系列的漏洞场…

【Python】从基础到进阶(一):了解Python语言基础以及变量的相关知识

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 引言一、Python简介1.1 历史背景1.2 设计哲学1.3 语言特性1.4 应用场景1.5 为什么选择Python 二、Python语言基础2.1 注释规则2.1.1 单行注释2.1.2 多行注释2.1.3 文件编码声明注释 2.2 代码缩进2.3 编码规范2.3.1 命名规范…

AlphaMissense:预测错义变异的致病性

错义变异或错义变体&#xff08;missense variation或missense variants&#xff09;是改变蛋白质氨基酸序列的遗传变异。致病性错义变异会严重破坏蛋白质功能&#xff0c;在目前观察到的400多万个错义变异中&#xff0c;只有2%在临床上被确定为致病或良性。对剩下的类型不明的…

力扣随机一题 模拟+字符串

博客主页&#xff1a;誓则盟约系列专栏&#xff1a;IT竞赛 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 1910.删除一个字符串中所有出现的给定子字符串【中等】 题目&#xff1a; …

【数据结构与算法】树的遍历,森林遍历 详解

树的先根遍历、后根遍历对应其二叉树的哪种遍历 树的先根遍历对应其二叉树的先序遍历&#xff08;根-左-右&#xff09;。树的后根遍历对应其二叉树的中序遍历&#xff08;左-根-右&#xff09;。 森林的先根遍历、中根遍历对应其二叉树的哪种遍历? 森林的先根遍历对应其二…

Elasticsearch 数据提取 - 最适合这项工作的工具是什么?

作者&#xff1a;来自 Elastic Josh Asres 了解在 Elasticsearch 中为你的搜索用例提取数据的所有不同方式。 对于搜索用例&#xff0c;高效采集和处理来自各种来源的数据的能力至关重要。无论你处理的是 SQL 数据库、CRM 还是任何自定义数据源&#xff0c;选择正确的数据采集…

《Deep learning practice》learning notes

学习笔记&#xff1a; 【公开课】旷视x北大《深度学习实践》&#xff08;28课时全&#xff09; R Talk | 旷视科技目标检测概述&#xff1a;Beyond RetinaNet and Mask R-CNN 文章目录 Lecture 1: Introduction to Computer Vision and Deep Learning&#xff08;孙剑&#x…

系统架构师考点--数据库系统

大家好。今天我来总结一下数据库系统的相关考点。本考点一般情况下上午场考试占3-5分&#xff0c;下午场案例分析题也会出现。 一、数据库系统 数据&#xff1a;数据库中存储的基本对象&#xff0c;是描述事物的符号记录。数据的种类:文本、图形、图像、音频、视频、学生的档…

AI/ML 数据湖参考架构架构师指南

这篇文章的缩写版本于 2024 年 3 月 19 日出现在 The New Stack 上。 在企业人工智能中&#xff0c;主要有两种类型的模型&#xff1a;判别模型和生成模型。判别模型用于对数据进行分类或预测&#xff0c;而生成模型用于创建新数据。尽管生成式人工智能最近占据了新闻的主导地…

【PyTorch】【机器学习】图片张量、通道分解合成和裁剪

一、导入所需库 from PIL import Image import torch import numpy as np import matplotlib.pyplot as plt二、读取图片 pic np.array(Image.open(venice-boat.jpg))上述代码解释&#xff1a;先用Image.open()方法读取jpg格式图片&#xff0c;再用np.array()方法将图片转成…