SpringBoot自动装配原理小结
作者:XPacific 发布时间:2023-11-18 16:54:06
目录
springboot autoconfig的一些实验
SpringBoot autoconfig部分注解说明
SpringBoot autoconfig原理
starter
约定优于配置(Convention Over Configuration)是一种软件设计范式,目的在于减少配置的数量或者降低理解难度,从而提升开发效率。
先总结一下结论:
springboot通过spring.factories能把main方法所在类路径以外的bean自动加载,其目的就是为了帮助自动配置bean,减轻配置量
springboot autoconfig的一些实验
一个springboot工程,springbootautoconfig.test.config这个包和启动类的包不再同一个路径下,那么这个包下的注解等应该不会生效,bean也无法托管给spring管理
@Configuration//开启配置
@EnableConfigurationProperties(HelloProperties.class)//开启使用映射实体对象
@ConditionalOnClass(TestHello.class)//存在TestHello时初始化该配置类
@ConditionalOnProperty//存在对应配置信息时初始化该配置类
(
prefix = "zxp.hello",//存在配置前缀zxp.hello
value = "flag"
)
public class HelloAutoConfiguration {
@Autowired
private HelloProperties helloProperties;
@Bean//创建HelloService实体bean
@ConditionalOnMissingBean(TestHello.class)//缺失HelloService实体bean时,初始化HelloService并添加到SpringIoc
public TestHello helloService()
{
System.out.println(">>>The TestHello Not Found,Execute Create New Bean.");
TestHello testHello = new TestHello(helloProperties.getName(),helloProperties.getFlag());
return testHello;
}
}
@ConfigurationProperties(prefix = "zxp.hello")
@Data
public class HelloProperties {
private String name;
private String flag;
}
public class TestHello {
String name;
String flag;
public TestHello(String name, String flag) {
this.name = name;
this.flag = flag;
}
public String print(){
String msg = "name is "+name + " " + "flag is "+flag;
System.out.println(msg);
return msg;
}
}
在resources下创建META-INF路径,并创建spring.factories文件
#配置自定义Starter的自动化配置
org.springframework.boot.autoconfigure.EnableAutoConfiguration=springbootautoconfig.test.config.HelloAutoConfiguration
再试启动又报错了
- Bean method 'helloService' not loaded because @ConditionalOnProperty (zxp.hello) did not find property 'flag'
原因是,如果没有配置zxp.hello.flag,怎会报错
@ConditionalOnProperty//存在对应配置信息时初始化该配置类
(
prefix = "zxp.hello",//存在配置前缀hello
value = "flag"//开启
)
在application.properties中添加
zxp.hello.flag=2
成功了,访问controller
name is null flag is 1
SpringBoot autoconfig部分注解说明
@ConditionalOnXxx 可以根据条件来决定是否执行自动配置
@ConditionalOnBean:当SpringIoc容器内存在指定Bean的条件
@ConditionalOnSingleCandidate:当指定Bean在SpringIoc容器内只有一个,或者虽然有多个但是指定首选的Bean
@ConditionalOnMissingBean:当SpringIoc容器内不存在指定Bean的条件
@ConditionalOnClass:当SpringIoc容器内存在指定Class的条件
@ConditionalOnMissingClass:当SpringIoc容器内不存在指定Class的条件
@ConditionalOnExpression:基于SpEL表达式作为判断条件
@ConditionalOnJava:基于JVM版本作为判断条件
@ConditionalOnJndi:在JNDI存在时查找指定的位置
@ConditionalOnResource:类路径是否有指定的值
@ConditionalOnProperty:指定的属性是否有指定的值
@ConditionalOnNotWebApplication:当前项目不是Web项目的条件
@ConditionalOnWebApplication:当前项目是Web项目的条件
@AutoConfigureBefore
@AutoConfigureAfter
@AutoConfigureOrder
public @interface ConditionalOnProperty {
String[] value() default {}; //数组,获取对应property名称的值,与name不可同时使用
String prefix() default "";//property名称的前缀,可有可无
String[] name() default {};//数组,property完整名称或部分名称(可与prefix组合使用,组成完整的property名称),与value不可同时使用
String havingValue() default "";//可与name组合使用,比较获取到的属性值与havingValue给定的值是否相同,相同才加载配置
boolean matchIfMissing() default false;//缺少该property时是否可以加载。如果为true,没有该property也会正常加载;反之报错
boolean relaxedNames() default true;//是否可以松散匹配,至今不知道怎么使用的
}
SpringBoot autoconfig原理
springboot启动类注解@SpringBootApplication引入@EnableAutoConfiguration又引入@Import(AutoConfigurationImportSelector.class)
AutoConfigurationImportSelector类中调用SpringFactoriesLoader.loadFactoryNames 方法扫描了所有JAR包的META-INF/spring.factories,如下代码:
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
……
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
spring-boot-autoconfigure包内的spring.factories文件内容
……
work.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
……
包含了所有spring为其增加的自动配置的bean配置,这些bean在满足条件后会被加载到spring上下文中,从而实现了自动配置
eg:
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ RabbitTemplate.class, Channel.class })
@EnableConfigurationProperties(RabbitProperties.class)
@Import(RabbitAnnotationDrivenConfiguration.class)
public class RabbitAutoConfiguration {
会发现RabbitTemplate会报错,为什么这里不存在的类却不报错呢? 1、这个jar编译时这个类是有的,保证编译能过 2、看下ConditionalOnClass注解的注释
The classes that must be present. Since this annotation is parsed by loading class bytecode, > it is safe to specify classes here that may ultimately not be on the classpath, only if this annotation is directly on the affected component and not if this annotation is used as a composed, meta-annotation. In order to use this annotation as a meta-annotation, only use the name attribute. Returns: the classes that must be present
必须出现的类。由于此注释是通过加载类字节码来解析的,因此在此处指定最终可能不在类路径上的类是安全的,前提是此注释直接位于受影响的组件上,而不是将此注释用作组合的元注释。要将此注释用作元注释,请仅使用name属性。
starter
starter就是整理了依赖的maven配置,主要指maven相关依赖配置到单独的一个工程以避免引入过多的maven配置
来源:https://juejin.cn/post/6966807647269945374#heading-2


猜你喜欢
- 什么是apllo开源分布式配置中心?apllo开源分布式配置中心是携程框架部门研发的一个能够集中化管理应用的不同环境、不同集群的配置,并且具
- using System.Drawing;using System.Drawing.Imaging;using System;using S
- 1.抽奖主界面2.操作步骤S键开始;0、1、2、3、4、5键分别对应6次奖项;分别是 特等奖、一等奖、二等奖、三等奖、四等奖、五等奖9键是加
- 在早期开发的时候,我们完成的都是静态页面也就是html页面,随着时间轴的发展,慢慢的引入了jsp页面,当在后端服务查询到数据之后可以转发到j
- 一、堆参数设置-XX:+PrintGC 使用这个参数,虚拟机启动后,只要遇到GC就会打印日志-XX:+UseSerialGC 配置串行回收器
- 标识符和关键字标识符读音 biao zhi fu什么是标识符包、类、变量、方法…等等,只要是起名的地方,那个名字就是标
- 脚本之家在以前介绍过关于C#创建、部署、调用WebService的教程,有兴趣的可以参阅:.NET C#创建WebService服务简单实例
- 1、什么是 ThreadLocal:ThreadLocal,即线程本地变量,如果你创建了一个变量,那么访问这个变量的每个线程都会有这个变量的
- 服装价格变动,触发淘宝发布活动和消费者购买衣服事件流public class EventStandard { &n
- 银行卡大家都使用,在密码输错超过限制次数之后,就容易被锁死,智能到银行柜台才能解锁,那么这一功能如果实现的呢,今天小编通过实例代码给大家详细
- Spring 基于注解启动主要有两个Class实现注解启动AnnotationConfigApplicationContextAnnotat
- 文章描述这个程序也记不清是什么时候写的了,犹记得那时我还很年轻,偶然从网上看到了这样一个类似的标题(AI五子棋的实现),进去后看到那个是ja
- 前言了解一下将 Android library 发布到中央仓库(比如 Maven Center,jitpack) 的过程中关于一些细节的疑惑
- 主要是应对这种需求:软件只允许启动一次。将这个问题转化一下,可以这样描述:对于一个软件,在启动一个进程之后,不允许启动其它进程,如果第二次打
- 如有错误,望指正;SpringBoot可以有三种方式定义初始化器,来为容器中增加自定义的对象,具体如下:1、定义在spring.factor
- #define Testusing System;namespace Wrox.ProCSharp.ParameterTestSample.
- 包装类包装类其实就是8种基本数据类型对应的引用类型。基本数据类型引用数据类型byteByteshortShortintIntegerlong
- 茫茫人海千千万万,感谢这一秒你看到这里。希望我的面试题系列能对你的有所帮助!共勉!愿你在未来的日子,保持热爱,奔赴山海!Java基础知识(继
- log4j2支持日志的异步打印,日志异步输出的好处在于,使用单独的进程来执行日志打印的功能,可以提高日志执行效率,减少日志功能对正常业务的影
- 自己整理了 spring boot 结合 Redis 的工具类引入依赖<dependency> <groupI