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 Boot Starter自动装配
以Spring boot 作为微服务开发的项目中会用到很多第三方,或者自建的一些依赖SDK,例如 分布式锁、文件管理、数据库连接、统一错误拦截等组件。为了达到通用的目的,都会创建自定义的spring boot stater 组件。以下介绍创建步骤:
一、创建Maven测试项目test-starter pom文件如下:
二、创建自动装配类TestServiceConfiguration.java
三、创建配置类TestServiceProperties.java
四、创建提供服务的接口TestService.java
五、创建TestService的实现类型TestServiceImpl.java
六、创建自定义注解@EnableTest
通过以上步骤就实现了自定义Spring boot starter test-spring-boot-starter 组件,下面创建测试项目去调用这个starter组件。
创建starter组件使用项目
一、创建maven测试项目test-service,pom文件如下
二、创建启动类Application.java
三、创建配置文件application.yml
四、创建测试类TestController.java
到这里整个自定义spring boot starter 创建就完成了,同时也依赖到项目中进行使用了。
项目代码:starter-test: 自定义starter组件
SpringBoot的自动装配(一)
一、什么是SpringBoot的自动装配
SpringBoot的自动装配是指:SpringBoot会自动将一些配置类的bean注册到ioc容器,我们可以在需要的地方使用@Autowired或@Resource等注解来使用它。
自动的表现形式就是我们只需要引我们享用功能的包,其他的配置完全不需要管,springboot会自动注入这些配置备案,我们直接使用就行。
自动装配也是SpringBoot的一个重要的特点,他帮我们做了很多的配置。
二、它是怎样实现的?
1、run方法
当启动一个SpringBoot项目时,本质上就是执行了地洞累中的主方法,然后执行了run方法。
ConfigurableApplicationContext这个对象就是 ApplicationContext接口的一个子接口。
其实SpringBoot项目的启动,本质上就是一个Spring的初始化操作。
2、@SpringBootApplication
点开这个注解可以发现,这是一个组合注解,包括:
这些注解中,前四个是JDK中的自动元注解,是用来修饰注解的注解。@ComponentScan是用来扫描路径的,如果不置顶特定的扫描路径的话,扫描的路径是当前修饰的类所在的包及其子包。而@SpringBootConfiguration这个注解的本质就是@Configuration注解。所以在这里面跟SpringBoot自动装配有关系的就只有一个了:@EnableAutoConfiguration
3、@EnableAutoConfiguration
@AutoConfigurationPackage不是用来实现自动装配的,在Spring中,他是用来扫描实体类Entity等注解的。所以重点是在@Import上。
@Import注解实现了AutoConfigurationImportSelector类,自动装配也是在这个类中进行了具体的实现。自动装配实现的就是该类中的selectImports方法里。通过selectImports方法,取到spring.factories文件下的一系列类名,随后将这些类自动加载至IOC容器中。
4、总结
SpringBoot的自动装配也就是通过@EnableAutoConfiguration注解,加载AutoConfigurationImportSelector类中的selectImports方法,进而扫描spring.factories文件下的自动配置类,并将其装配到IOC容器的过程。
SpringBoot自动配置/装配(SPI)
自己动手写一个启动器的经历:
这里报错了,原因是只导入了一个bean而SpringBoot无法启动服务器
解决办法一:将@Import改成@ConponentScan这样就会扫描同级包和子包。
解决办法二:关闭web服务器
自动装配的大概流程 :@EnableAutoConfiguration目的是自动装配在Maven中的第三方依赖,然后通过@Import(seleter)导入selecter,再通过selecter找到对应的.factories文件最终加载了打上@Configuration的文件。
首先开启了自动装配
通过Selector方法返回对应的类的名字
SPI全名为Service Provider Interface
模块 实现方案
| | | | | | | 方案A
调用方 标准服务接口 方案B
| | | | | | | 方案C
基于interface + 策略模式 + 配置模式
整体解决方案的变化
与@Primary@条件注解的区别:具体/粒度小。