[Spring 从模拟开始学习源码]`@Value`的底层实现
2023-12-18 08:46:09
@Value 注入主要有三种场景:
- 注入原始值,比如说注入
Value("hello")
- 注入变量,比如
@Value("${JAVA_HOME}")
- 注入spel表达式,比如
@Value("#{1 + 2}")
package com.example.value;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
@Configuration // 自动扫描bean3
public class ValueApplication {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(ValueApplication.class);
DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
ContextAnnotationAutowireCandidateResolver resolver =
new ContextAnnotationAutowireCandidateResolver();
resolver.setBeanFactory(beanFactory);
test1(context, resolver);
test2(context, resolver);
test3(context, resolver, Bean2.class.getDeclaredField("bean3"));
System.out.println(">>>>>>>>>>>>>>>>>>>");
test3(context, resolver, Bean4.class.getDeclaredField("value"));
}
private static void test1(AnnotationConfigApplicationContext context,
ContextAnnotationAutowireCandidateResolver resolver) throws Exception {
DependencyDescriptor dd1 =
new DependencyDescriptor(Bean1.class.getDeclaredField("home"), false);
// 获取 @Value 的内容
String value = resolver.getSuggestedValue(dd1).toString();
System.out.println(value);
// 解析 ${}
value = context.getEnvironment().resolvePlaceholders(value);
System.out.println(value);
}
// ${} -> 类型
private static void test2(AnnotationConfigApplicationContext context,
ContextAnnotationAutowireCandidateResolver resolver) throws Exception{
DependencyDescriptor dd1 =
new DependencyDescriptor(Bean1.class.getDeclaredField("age"), false);
// 获取 @Value 的内容
String value = resolver.getSuggestedValue(dd1).toString();
System.out.println("@Value 的 value 属性值: " + value);
// 解析 ${}
value = context.getEnvironment().resolvePlaceholders(value);
System.out.println("解析得到的值: " + value);
System.out.println("解析得到的值的类型: " + value.getClass());
// 转成字段的类型
Object age = context.getBeanFactory()
.getTypeConverter()
.convertIfNecessary(value, dd1.getDependencyType());
System.out.println("转换后的类型: " + age.getClass());
}
// spel
private static void test3(AnnotationConfigApplicationContext context,
ContextAnnotationAutowireCandidateResolver resolver,
Field field) throws Exception {
DependencyDescriptor dd1 = new DependencyDescriptor(field, false);
// 获取 @Value 的内容
String value = resolver.getSuggestedValue(dd1).toString();
System.out.println("@Value 的 value 属性值: " + value);
// 解析 ${}
value = context.getEnvironment().resolvePlaceholders(value);
System.out.println("解析得到的值: " + value);
System.out.println("解析得到的值的类型: " + value.getClass());
// 解析 #{}
Object bean3 = context.getBeanFactory()
.getBeanExpressionResolver()
.evaluate(value, new BeanExpressionContext(context.getBeanFactory(), null));
// 类型转换
Object result = context.getBeanFactory()
.getTypeConverter()
.convertIfNecessary(bean3, dd1.getDependencyType());
System.out.println("转换后的类型: " + result.getClass());
}
static class Bean1 {
@Value("${JAVA_HOME}")
private String home;
@Value("18")
private int age;
}
static class Bean2 {
@Value("#{@bean3}")
private Bean3 bean3;
}
@Component("bean3")
static class Bean3 {
}
static class Bean4 {
@Value("#{'hello, ' + '${JAVA_HOME}'}")
private String value;
}
}
输出结果
${JAVA_HOME}
/Users/xx/Library/Java/JavaVirtualMachines/corretto-17.0.8.1/Contents/Home
@Value 的 value 属性值: 18
解析得到的值: 18
解析得到的值的类型: class java.lang.String
转换后的类型: class java.lang.Integer
@Value 的 value 属性值: #{@bean3}
解析得到的值: #{@bean3}
解析得到的值的类型: class java.lang.String
转换后的类型: class com.example.value.ValueApplication$Bean3
>>>>>>>>>>>>>>>>>>>
@Value 的 value 属性值: #{'hello, ' + '${JAVA_HOME}'}
解析得到的值: #{'hello, ' + '/Users/xx/Library/Java/JavaVirtualMachines/corretto-17.0.8.1/Contents/Home'}
解析得到的值的类型: class java.lang.String
转换后的类型: class java.lang.String
用到的几个工具类
获取 @Value
内容
Bean2.class.getDeclaredField("bean3")
DependencyDescriptor dd1 = new DependencyDescriptor(field, false);
// 获取 @Value 的内容
String value = resolver.getSuggestedValue(dd1).toString();
解析 ${}
内容
value = context.getEnvironment().resolvePlaceholders(value);
解析 SPEL
Object bean3 = context.getBeanFactory()
.getBeanExpressionResolver()
.evaluate(value, new BeanExpressionContext(context.getBeanFactory(), null));
类型转换
Object result = context.getBeanFactory()
.getTypeConverter()
.convertIfNecessary(bean3, dd1.getDependencyType());
文章来源:https://blog.csdn.net/qq_45704048/article/details/135051808
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!