Spring boot 的@Value只能用于bean中,在bean的实例化时,会给@Value的属性赋值:如下面的例子:

@SpringBootApplication
@Slf4j
public class DemoApplication { @Value(value = "${server.port}")
private String config; public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }
}

下面的类显示了bean的实例化方法:org.springframework.context.support.AbstractApplicationContext

@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh(); // Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory); try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory); // Initialize message source for this context.
initMessageSource(); // Initialize event multicaster for this context.
initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses.
onRefresh(); // Check for listener beans and register them.
registerListeners(); // 实例化方法 Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event.
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
} // Destroy already created singletons to avoid dangling resources.
destroyBeans(); // Reset 'active' flag.
cancelRefresh(ex); // Propagate exception to caller.
throw ex;
} finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}

bean的具体实例过过程,就不在这里说了,具体可以看前面的文章Spring boot IOC源码解析.

这个方法中:org.springframework.beans.factory.annotation.InjectionMetadata#inject 会遍历bean中所有的成员:

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
element.inject(target, beanName, pvs);
}
}
}

这个方法会读取出要取值的Vaule:org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency

@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
} Class<?> type = descriptor.getDependencyType();
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); // 取出server.port
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);//解析出具体的value
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
} Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
} Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
} String autowiredBeanName;
Object instanceCandidate; if (matchingBeans.size() > 1) {
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
} if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}

最终解析的代码如下:org.springframework.core.env.PropertySourcesPropertyResolver#getProperty(java.lang.String, java.lang.Class<T>, boolean)

@Nullable
protected <T> T getProperty(String key, Class<T> targetValueType, boolean resolveNestedPlaceholders) {
if (this.propertySources != null) {
for (PropertySource<?> propertySource : this.propertySources) {
if (logger.isTraceEnabled()) {
logger.trace("Searching for key '" + key + "' in PropertySource '" +
propertySource.getName() + "'");
}
Object value = propertySource.getProperty(key);
if (value != null) {
if (resolveNestedPlaceholders && value instanceof String) {
value = resolveNestedPlaceholders((String) value);
}
logKeyFound(key, propertySource, value);
return convertValueIfNecessary(value, targetValueType);
}
}
}
if (logger.isTraceEnabled()) {
logger.trace("Could not find key '" + key + "' in any property source");
}
return null;
}
propertySource的内容,可以看上篇博客,里面记录了spring boot是如何读取配置文件信息的。

详细的调用堆栈信息如下:

这里还有一个顺序的问题:

比如:有三个配置文件:

系统加载出来是这个样子的

每个配置文件,我都配置了:

server:
port: ****

那它会最终读取哪个配置文件的端口呢?

答案就是加上面的顺序,找到了第一个就返回了,后面的不管了。

也就是说dev的优先,(加了profile的)  然后是不加的,最后是bootstrap的。

spring boot @Value源码解析的更多相关文章

  1. Spring Boot 启动源码解析结合Spring Bean生命周期分析

    转载请注明出处: 1.SpringBoot 源码执行流程图 2. 创建SpringApplication 应用,在构造函数中推断启动应用类型,并进行spring boot自动装配 public sta ...

  2. Spring Security 解析(七) —— Spring Security Oauth2 源码解析

    Spring Security 解析(七) -- Spring Security Oauth2 源码解析   在学习Spring Cloud 时,遇到了授权服务oauth 相关内容时,总是一知半解,因 ...

  3. Feign 系列(05)Spring Cloud OpenFeign 源码解析

    Feign 系列(05)Spring Cloud OpenFeign 源码解析 [TOC] Spring Cloud 系列目录(https://www.cnblogs.com/binarylei/p/ ...

  4. 异步任务spring @Async注解源码解析

    1.引子 开启异步任务使用方法: 1).方法上加@Async注解 2).启动类或者配置类上@EnableAsync 2.源码解析 虽然spring5已经出来了,但是我们还是使用的spring4,本文就 ...

  5. Spring Security 访问控制 源码解析

    上篇 Spring Security 登录校验 源码解析  分析了使用Spring Security时用户登录时验证并返回token过程,本篇分析下用户带token访问时,如何验证用户登录状态及权限问 ...

  6. Spring @Import注解源码解析

    简介 Spring 3.0之前,创建Bean可以通过xml配置文件与扫描特定包下面的类来将类注入到Spring IOC容器内.而在Spring 3.0之后提供了JavaConfig的方式,也就是将IO ...

  7. api网关揭秘--spring cloud gateway源码解析

    要想了解spring cloud gateway的源码,要熟悉spring webflux,我的上篇文章介绍了spring webflux. 1.gateway 和zuul对比 I am the au ...

  8. Spring Boot缓存源码分析

    前言 项目里面要增加一个应用缓存,原本想着要怎么怎么来整合ehcache和springboot,做好准备配置这个配置那个,结果只需要做三件事: pom依赖 写好一个ehcache的配置文件 在boot ...

  9. Spring容器启动源码解析

    1. 前言 最近搭建的工程都是基于SpringBoot,简化配置的感觉真爽.但有个以前的项目还是用SpringMvc写的,看到满满的配置xml文件,却有一种想去深入了解的冲动.折腾了好几天,决心去写这 ...

随机推荐

  1. iOS真机调试之免费预配(Free provisioning)

    免费预配允许开发者在不加入Applec Developer Program的情况下,可以发布和测试App 注意:免费预配(Free Provisioning)与自动预配(Auto Provisioni ...

  2. ccf 201712-4 行车路线(70分)

    ccf 201712-4 行车路线 解题思路: 首先Dijkstra是基于贪心算法的,即每一次作出的选择都具有贪心选择性.此题由于有“如果连续走小道,小明的疲劳值会快速增加,连续走s公里小明会增加s2 ...

  3. 【导航】JennyHui 老白兔记录贴

    英语控 TED X - > 笔记 程序媛 2019-08-24 Java学习路径规划 思考记录 2018-08-24 常见的工作思考方式 浪费时间 百家讲坛 开卷八分钟

  4. LC 889. Construct Binary Tree from Preorder and Postorder Traversal

    Return any binary tree that matches the given preorder and postorder traversals. Values in the trave ...

  5. tableau extension 调研

    概述 最近调研了一下 tableau extensions 的实现,有一些心得,记录下来,供以后开发时参考,相信对其他人也有用. 总的来说,写 tableau extensions 还是挺简单的,只是 ...

  6. ElementTree 无法处理中文

    ElementTree.fromstring()  导入xml格式时,是可以选择解析parser的编码的,并且 它解析出来的node类型是 严谨且严格的,不会 自己内部全部转换成str,比如 9.87 ...

  7. spring_quartz的实现

    一.在spring配置文件中引用对应的定时任务配置文件 二.定义定时任务的业务代码 三.配置定时任务配置文件spring-quartz.xml <?xml version="1.0&q ...

  8. Ubunut16.04 安装 Mahout

    近期笔者想安装mahout,看到网上教程过于陈旧,故记录之 转载请包含 http://www.cnblogs.com/lqruui/p/6037680.html 1.下载mahout   mahout ...

  9. ModelAndView及页面转发

    1.ModelAndView springMVC中返回值如果是ModelAndView,则其既包含模型数据信息,也包含视图信息. 在处理方法中可以使用ModelAndView对象的方法添加模型数据:a ...

  10. three中的着色器示例

    其实在3D引擎/库的帮助下,我们做webgl开发的难度已经很大大地降低了,熟悉相关API的话,开发一个简单的3D程序可以说是很轻松的事情. 在我看来,webgl的核心就是着色器(顶点着色器.片元着色器 ...