首页>>后端>>SpringBoot->springboot自动注入原理(springboot如何注入自定义类)

springboot自动注入原理(springboot如何注入自定义类)

时间:2023-12-01 本站 点击:0

SpringBoot自动配置的原理及实现/SpringBoot之@Import注解正确使用方式

了解SpringBoot之@Import注解正确使用方式

SpringBoot 的核心就是自动配置,自动配置又是基于条件判断来配置 Bean。关于自动配置的源码在 spring-boot -autoconfigure-2.0.3.RELEASE.jar

在通常需要我们在 property 中配置信息时,通常使用 @ConfigurationProperties(pefix=“前缀”) 注解的方式从配置文件中获取配置,如下:

application.yml 中配置信息

访问 url 获取配置信息返回的值

如果把 application.yml 中的配置信息注释掉则默认使用 default 值,否则使用配置信息中的值,以上便是普通配置方式

SpringBoot 运行原理

先看 @SpringBootApplication

主要关注的几个注解如下

@SpringBootConfiguration:标记当前类为配置类

@EnableAutoConfiguration:开启自动配置

@ComponentScan:扫描主类所在的同级包以及下级包里的 Bean

关键是 @EnableAutoConfiguration

最关键的要属 @Import(EnableAutoConfigurationImportSelector.class),借助** EnableAutoConfigurationImportSelector**,@EnableAutoConfiguration 可以帮助 SpringBoot 应用将所有符合条件的 @Configuration 配置都加载到当前 SpringBoot 创建并使用的 IoC 容器: 通过 @Import(AutoConfigurationImportSelector.class) 导入的配置功能,

AutoConfigurationImportSelector 中的方法 getCandidateConfigurations,得到待配置的 class 的类名集合, 这个集合就是所有需要进行自动配置的类,而是是否配置的关键在于 META-INF/spring.factories 文件中是否存在该配置信息

打开,如下图可以看到所有需要配置的类全路径都在文件中,每行一个配置,多个类名逗号分隔, 而 \ 表示忽略换行

整个流程如上图所示

以 SpringApplicationAdminJmxAutoConfiguration 类来看其主要构成部分

都能看到各种各样的条件判断注解,满足条件时就加载这个 Bean 并实例化

此类的条件注解是:@ConditionalOnProperty

@ConditionalOnBean:当容器里有指定 Bean 的条件下

@ConditionalOnClass:当类路径下有指定的类的条件下

@ConditionalOnExpression:基于 SpEL 表达式为 true 的时候作为判断条件才去实例化

@ConditionalOnJava:基于 JVM 版本作为判断条件

@ConditionalOnJndi:在 JNDI 存在的条件下查找指定的位置

@ConditionalOnMissingBean:当容器里没有指定 Bean 的情况下

@ConditionalOnMissingClass:当容器里没有指定类的情况下

@ConditionalOnWebApplication:当前项目时 Web 项目的条件下

@ConditionalOnNotWebApplication:当前项目不是 Web 项目的条件下

@ConditionalOnProperty:指定的属性是否有指定的值

@ConditionalOnResource:类路径是否有指定的值

@ConditionalOnOnSingleCandidate:当指定 Bean 在容器中只有一个,或者有多个但是指定首选的 Bean

这些注解都组合了 @Conditional 注解,只是使用了不同的条件组合最后为 true 时才会去实例化需要实例化的类,否则忽略

这种 spring4.X 带来的动态组合很容易后期配置,从而避免了硬编码,使配置信息更加灵活多变,同时也避免了不必要的意外异常报错。使用的人只要知道配置的条件即可也不用去阅读源码,方便快捷,这也是 sprignboot 快捷方式带来的好处

参考 HttpEncodingAutoConfiguration 配置信息如下

案例扩展

项目

需要实例化的服务类

配置信息对应的属性映射类, 需要 pom 中加入 spring-boot-starter 依赖

自动配置文件

在创建如下路径文件 src/main/resources/META-INF/spring.factories

必须是自动配置类的全路径

mvn install 该项目

创建一个 springboot-mvc 项目 pom 依赖上面的 jar

/ 则返回当前服务的默认值

在 applicaton.yml 中加, 重启刷新则会更新为如下信息

SpringBoot 自动化配置关键组件关系图

mybatis-spring-boot-starter、spring-boot-starter-web 等组件的 META-INF 文件下均含有 spring.factories 文件,自动配置模块中,SpringFactoriesLoader 收集到文件中的类全名并返回一个类全名的数组,返回的类全名通过反射被实例化,就形成了具体的工厂实例,工厂实例来生成组件具体需要的 bean。

在 spring boot 中有时候需要控制配置类是否生效, 可以使用 @ConditionalOnProperty 注解来控制 @Configuration 是否生效.

boot自动配置的原理

Spring Boot是基于Spring开发的,是约定大于配置的核心思想。并且集成了大量的第三方库配置比如redis、mongoDB、jpa等。Spring Boot就相当于maven整合了所有jar包,Spring Boot整合了所有框架。其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程,并不少什么新的框架。

二、Spring Boot优点

优点其实就是简单、快速

快速创建独立运行的Spring项目以及主流框架集成

使用嵌入式的server容器,应用无需打成WAR包

starters自动依赖与版本控制

有大量的自动配置,简化开发

准生产环境运行应用监控

与云计算的天然集成

Spring Boot主程序分析

//@SpringBootApplication标注这个类是一个Springboot的应用@SpringBootApplicationpublicclassSpringboot02DemoApplication{publicstaticvoidmain(String[] args){//将Springboot应用启动 SpringApplication.run(Springboot02DemoApplication.class, args);}}

SpringBootApplication源码剖析,进入源码,结果发现其实它是一个组合注解

第一个SpringBootConfiguration注解:@SpringBootConfiguration--是Spring Boot配置类。下面有一个叫@Configuration:它是配置类,下面又有@Component,其实它就是一个注入组件。

第二个@EnableAutoConfiguration注解:是开启自配配置功能

@AutoConfigurationPackage//自动配置包

@Import(AutoConfigurationImportSelector.class)

public @interface EnableAutoConfiguration {}

@AutoConfigurationPackage:自动配置包,使用@Import(AutoConfigurationImportSelector.class)注解来完成的,它是spring boot底层注解,作用是给容器中导入组件。

自动配置原理

(1)Spring Boot启动的时候首先加载主配置类,开启啦自动配置的功能(@EnableAutoConfiguration)

(2)自动配置功能@EnableAutoConfiguration的作用:它是利用了

@Import(AutoConfigurationImportSelector.class)给容器中导入一些组件。那么,他会给我们导入哪些组件呢?进入AutoConfigurationImportSelector源码看一下部分源码如下。

//@EnableAutoConfiguration注解

@AutoConfigurationPackage

/@Import(AutoConfigurationImportSelector.class)

public @interface EnableAutoConfiguration

@Import(AutoConfigurationImportSelector.class)自动配置导入选择

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,

ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {

//----部分源码省略----//

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {

if (!isEnabled(annotationMetadata)) {

return EMPTY_ENTRY;

}

AnnotationAttributes attributes = getAttributes(annotationMetadata);

ListString configurations = getCandidateConfigurations(annotationMetadata, attributes);

//----部分源码省略----//

}

Spring Boot源码-@EnableConfigurationProperties @ConfigurationProperties注解配置原理

1 概述

2 实例

3 配置注入实现原理

使用过Spring Boot的都会知道,我们可以在application.properties文件中进行一系列的配置,该配置会被自动注入到我们需要使用的bean中,下面我们就介绍配置注入的实现原理。

首先,要知道在application.properties中的配置是通过 BeanPostProcessor 进行注入的,具体完成该功能的 BeanPostProcessor 实现类是 ConfigurationPropertiesBindingPostProcessor 。

本文接下来会介绍 ConfigurationPropertiesBindingPostProcessor 是在何时被加入到beanfactory中的,以及 @EnableConfigurationProperties 、 @ConfigurationProperties 注解的实现原理。

Spring Boot自动配置中充斥着大量使用通过application.properties进行扩展配置的实现,比如我们熟悉的 MybatisAutoConfiguration :

下面我们在看下 MybatisProperties 类的定义:

通过如上的注解,MyBatis就可以获得我们在application.properties中的配置了,比如如下配置:

要了解配置注入的实现原理,首先要找到上文介绍到的 ConfigurationPropertiesBindingPostProcessor 是何时被注册到beanfactory中的,通过阅读源码发现,在spring.factories文件中有如下一行:

可见,是通过 @EnableAutoConfiguration 注解引入了相关的配置, @EnableAutoConfiguration 通过 @Import 注解自动配置的原理这里不再介绍。我们看下 ConfigurationPropertiesAutoConfiguration 类的实现:

首先 ConfigurationPropertiesAutoConfiguration 被 @Configuration 注解,因此会在beanfactory加载时被作为配置类处理,具体在 ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry 调用 ConfigurationClassParser.parse 进行处理。

我们再看 @EnableConfigurationProperties 定义:

@EnableConfigurationProperties 通过 @Import(EnableConfigurationPropertiesImportSelector.class) 向容器中注入了相关的处理类, @Import 也是在 ConfigurationClassParser.parse 进行处理的。

EnableConfigurationPropertiesImportSelector 类定义如下:

好了,到这里,我们已经知道注解@ EnableConfigurationProperties.value 中指定的配置类是如何被注入到beanfactory中的了,那么注解 EnableConfigurationProperties.value 中指定的配置类中的属性是如何从application.properties被注入的呢?比如上面的

对应配置如下:

这就是我们前面提到的 BeanPostProcessor 接口实现类 ConfigurationPropertiesBindingPostProcessor 类处理的,而 ConfigurationPropertiesBindingPostProcessor 则是通过上面 EnableConfigurationPropertiesImportSelector 中使用类 ConfigurationPropertiesBindingPostProcessorRegistrar 进行注册的:

ConfigurationPropertiesBindingPostProcessor 是接口 BeanPostProcessor 的实现,会被 ApplicationContext 检测出来,在实例化每个bean时会被调用进行扩展处理。

SpringBoot自动装配原理

初看@SpringBootApplication有很多的注解组成,其实归纳就是一个"三体"结构,重要的只有三个Annotation:

(1)@Configuration注解

(2)@ComponentScan

(3)@EnableAutoConfiguration

从源码中可以知道,最关键的要属@Import(EnableAutoConfigurationImportSelector.class),借助EnableAutoConfigurationImportSelector,@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器。同时借助于Spring框架原有的一个工具类:SpringFactoriesLoader,@EnableAutoConfiguration就可以实现智能的自动配置。

总结 :@EnableAutoConfiguration作用就是从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure.EnableutoConfiguration对应的配置项通过反射(Java Refletion)实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。这些功能配置类要生效的话,会去classpath中找是否有该类的依赖类(也就是pom.xml必须有对应功能的jar包才行)并且配置类里面注入了默认属性值类,功能类可以引用并赋默认值。生成功能类的原则是自定义优先,没有自定义时才会使用自动装配类。

1、从spring-boot-autoconfigure.jar/META-INF/spring.factories中获取redis的相关配置类全限定名(有120多个的配置类)RedisAutoConfiguration,一般一个功能配置类围绕该功能,负责管理创建多个相关的功能类,比如RedisAutoConfiguration负责:JedisConnectionFactory、RedisTemplate、StringRedisTemplate这3个功能类的创建

2、RedisAutoConfiguration配置类生效的一个条件是在classpath路径下有RedisOperations类存在,因此springboot的自动装配机制会会去classpath下去查找对应的class文件。

3.如果pom.xml有对应的jar包,就能匹配到对应依赖class,

4、匹配成功,这个功能配置类才会生效,同时会注入默认的属性配置类@EnableConfigurationProperties(RedisProperties.class)

5.Redis功能配置里面会根据条件生成最终的JedisConnectionFactory、RedisTemplate,并提供了默认的配置形式@ConditionalOnMissingBean(name = "redisTemplate")

6.最终创建好的默认装配类,会通过功能配置类里面的 @Bean注解,注入到IOC当中

7.用户使用,当用户在配置文件中自定义时候就会覆盖默认的配置@ConditionalOnMissingBean(name = "redisTemplate")

1.通过各种注解实现了类与类之间的依赖关系,容器在启动的时候Application.run,会调用EnableAutoConfigurationImportSelector.class的selectImports方法(其实是其父类的方法)-- 这里需要注意,调用这个方法之前发生了什么和是在哪里调用这个方法需要进一步的探讨

2.selectImports方法最终会调用SpringFactoriesLoader.loadFactoryNames方法来获取一个全面的常用BeanConfiguration列表

3.loadFactoryNames方法会读取FACTORIES_RESOURCE_LOCATION(也就是spring-boot-autoconfigure.jar 下面的spring.factories),获取到所有的Spring相关的Bean的全限定名ClassName,大概120多个

4.selectImports方法继续调用filter(configurations, autoConfigurationMetadata);这个时候会根据这些BeanConfiguration里面的条件,来一一筛选,最关键的是

@ConditionalOnClass,这个条件注解会去classpath下查找,jar包里面是否有这个条件依赖类,所以必须有了相应的jar包,才有这些依赖类,才会生成IOC环境需要的一些默认配置Bean

5.最后把符合条件的BeanConfiguration注入默认的EnableConfigurationPropertie类里面的属性值,并且注入到IOC环境当中

spring表达式注入原理

开门见山。SpringBean的注入原理:

spring是在配置类需要指定扫描包,然后递归得到下面所有的文件;(springboot默认启动类和兄弟目录下面所有的包文件)

包名+文件名=类全限定名;

calss.from加载到内存当中,得到字节码(class);

判断这个类的脑门上是否有注解(就是类的头顶上),有注解的话,就把这个类先put到Map里面(ResourcesMap和autowiredMap各一份);

如果这个类下面有注解的话@Resources就去ResourcesMap里面去遍历,得到对象,然后注入进来,@Autowired就去AutowiredMap里面去遍历,然后得到对象,注入进来;

实体类脑门上没有注解是没有注入到IOC的。

SpringBoot运行原理

SpringBoot是一个基于Spring开发,集成了大量第三方库配置的javaweb开发框架

pom.xml

父依赖

其中它主要是依赖一个父项目,主要是管理项目的资源过滤及插件。以后我们导入依赖默认是不需要写版本的。

启动器spring-boot-starter

springboot-boot-starter-xxx:spring-boot的场景启动器

spring-boot-starter-web:帮我们导入了web模块正常运行所依赖的组件。

springBoot将所有的功能场景都抽取出来,做成一个个的starter(启动器),只需要在项目中引入这些starter即可,所有相关的依赖都会被引进来,我们要用什么功能就导入什么样的场景启动器即可。

@SpringBootApplication

作用:标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot运行这个类的main方法来启动SpringBoot应用。

进入这个注解,里面包含了很多其他注解

@ComponentScan作用:自动扫描并加载符合条件的组件或者bean,将这个bean定义加载到IOC容器中。

@SpringBootConfiguration作用:SpringBoot的配置类,标注在某个类上,表示这是一个SpringBoot的配置类。

进入@SpringBootConfiguration注解查看,这里的@Configuration说明这是一个配置类,配置类对应Spring的xml配置文件。

继续查看@SpringBootConfiguration包含的其他注解

@EnableAutoConfiguration:开启自动配置功能

进入@EnableAutoConfiguration注解查看

@AutoConfigurationPackage自动配置包

@import:Spring底层注解@import,给容器中导入一个组件

@Import({AutoConfigurationImportSelector.class})给容器导入组件

AutoConfigurationImportSelector:自动配置导入选择器。那么它导入哪些组件的选择器呢

这个类中有这样一个方法:getCandidateConfiguration,而在这个方法中有调用了SpringFactoriesLoader类的静态方法loadFactoryNames()方法

进入loadSpringFactories方法

根据全局搜索Spring.factories,打开后是自动配置的文件。

随便打开一个其中的自动配置类看,它们都是javaConfig配置类,都注入了一些Bean

所以,自动配置真正实现是从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中对应的org.springframework.boot.autoconfigure包下的配置项通过反射实例化为对应标注了@Configuration的javaConfig形式的IOC容器配置类,然后将这些都汇总成为一个实例并加载到IOC容器中。

结论:

1.SpringBoot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值

2.将这些值作为自动配置类导入容器,自动配置类就生效,帮我们进行自动配置工作。

3.整个J2EE的整体解决方案和自动配置都在springboot-autoConfigure的jar包中。

4.它会给容器中导入非常多的自动配置类(xxxAutoConfiguration),就是给容器中导入这个场景需要的所有组件,并配置好这些组件。

5.有了自动配置类,免去了我们手动编写配置注入功能组件等的工作。

SpringApplication

这个类主要做了以下四件事

1.推断应用的类型是普通的项目还是web项目

2.查找并加载所有可用初始化器,设置到initializers属性中

3.找出所有的应用程序监听器,设置到listeners属性中

4.推断并设置main方法的定义类,找到运行的主类


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