springboot-ObjectToObjectConverter发现
springboot属性绑定
在springboot现在如日中天的时候,虽然很多人都在用它,但是有些伙伴可能并不知道它的神秘之处,或许或多或少有一些疑问?
比如:
- 跟着官网愉快的在application配置文件配置了一堆堆文本,怎么变成转换到java类的各个属性的呢?
gateway引发今天的思考
最近笔者在学习gateway的路由predicate、filters的配置,就是在思考怎么转换成对象RouteDefinition,所以今天特地深入研究下。
思考:
- 首先RouteDefinition也是属于GatewayProperties的一个属性,所以我们配置的一大堆东西肯定是被映射到GatewayProperties上的
- 大家都知道,GatewayProperties是一个@ConfigurationProperties(“spring.cloud.gateway”),即有一个ConfigurationPropertiesBindingPostProcessor后置处理器来处理,这里先不做详细介绍,先讲重点
- 我们知道在spring中,属性绑定有两个重要组件PropertyEditor和Converter(两个作用都是将一个值,转换为另一个值)
- 经过我仔细一层层查找,发现ConfigurationPropertiesBindingPostProcessor也同样包括PropertyEditor和Converter,这样真相大白了
(想发散的同学,可以根据ConfigurationPropertiesBinder类去先熟悉熟悉)
ConfigurationPropertiesBinder
private Binder getBinder() {
if (this.binder == null) {
//在这里发现,这个binder对象,拥有ConversionService(这个对象拥有我们所需要的的List<Converter>集合)
this.binder = new Binder(getConfigurationPropertySources(), getPropertySourcesPlaceholdersResolver(),
getConversionService(), getPropertyEditorInitializer(), null,
ConfigurationPropertiesBindConstructorProvider.INSTANCE);
}
return this.binder;
}
- 有意思的是,在springboot中,这个ConversionService接口对象(实际对象是ApplicationConversionService类)是一个,用双层检查锁DCL(double check lock)来实现的线程安全的单例
//ApplicationConversionService类中
public static ConversionService getSharedInstance() {
ApplicationConversionService sharedInstance = ApplicationConversionService.sharedInstance;
if (sharedInstance == null) {
synchronized (ApplicationConversionService.class) {
sharedInstance = ApplicationConversionService.sharedInstance;
if (sharedInstance == null) {
sharedInstance = new ApplicationConversionService();
ApplicationConversionService.sharedInstance = sharedInstance;
}
}
}
return sharedInstance;
}
- 更有意思的是,这个类实际上在springboot的SpringApplication启动在configureEnvironment这一步的时候,就已经默认加载了
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
//这个默认是true
if (this.addConversionService) {
//ApplicationConversionService的单例加载
ConversionService conversionService = ApplicationConversionService.getSharedInstance();
environment.setConversionService((ConfigurableConversionService) conversionService);
}
configurePropertySources(environment, args);
configureProfiles(environment, args);
}
ObjectToObjectConverter
-
在ApplicationConversionService类初始化的时候,就会添加很多很多Converter,在#addDefaultConverters方法中我们就可以找到今天的主角。
-
通过看代码和代码注释,可以得出ObjectToObjectConverter类进行转换有几个关注方法。
代码可以各位去看,我就不贴出来了,只是根据具体例子来演示。这个我们先定义好源类型和目标类型(想要转换的类型)
源类型SourceClass => String.class (因为我们配置的东西大多都是字符串)
源的值 SourceValue => “abc”
目标类型TargetClass => People.class (假设我们有一个People对象)
- determineToMethod
指的是:在SourceClass类中查找to${TargetClass.simpleClassName}的方法。
在这里的例子中,也就是在String类中,查找toPeople的方法,如果找不到,则跳过
public People toPeople(String source){}
不过我们也不可能在String类中定义方法,所以这个determineToMethod 有判断,只要任何一方为String类型,就直接返回null
if (String.class == targetClass || String.class == sourceClass) {
// Do not accept a toString() method or any to methods on String itself
return null;
}
- determineFactoryMethod
指的是: 在TargetClass中查找静态方法,valueOf、 of 、from方法
在这里的例子中,就是在People中查找如下三种方法,进行工厂方法转换
public static People valueOf (String source){}
public static People of (String source){}
public static People from(String source){}
- 如果找不到valueOf、of 、from三种方法,则最后一步,根据构造函数转换
- determineFactoryConstructor
指的是: 根据构造函数转换对象
也就是在People类中,查找source的构造函数,进行转换
public People(String source){}
Gateway验证
- 通过ObjectToObjectConverter我们知道了,springboot可以通过静态方法、构造方法在进行转换创建对象
- 我们发现RouteDefinition,PredicateDefinition,FilterDefinition 都有一个带有String类型的构造函数,这细细猜想就可以得出,gateway的属性绑定,就是通过ObjectToObjectConverter的构造函数创建的。
本文地址:https://blog.csdn.net/he702170585/article/details/107332094
上一篇: AOP简介
下一篇: 冒泡、Arrays用法与维数组
推荐阅读
-
00后发现财富秘籍:抖音小店无货源,月利润流水高达10w
-
微服务(入门三):netcore ocelot api网关结合consul服务发现
-
一起来学Spring Cloud | 第二章:服务注册和发现组件 (Eureka)
-
发现细节之美:网页页脚设计技巧大放送
-
everything is beautiful php intval的测试代码发现问题
-
在修改准备发的批量美化select+可修改select时,在非IE下发现了几个问题_表单特效
-
工作中发现Web服务器的磁盘满后故障分析
-
360发现苹果MacOS蓝牙漏洞 可实现无接触远程控制
-
Django3.2 自动发现所有路由代码详解
-
你发现了吗?高德地图率先上线“极速绿”新路况:更精准