学一学Spring中的@Value

Spring版本: 5.3.27

JDK版本: 1.8

1、MyConfig.properties何时被加载解析?

2、MyService中的两个@Value何时解析?

3、MyService中的两个@Value何时注入属性文件中的值?

一、样例

服务类

kotlin 复制代码
 package com.lazy.snail.service;
 ​
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 ​
 /**
  * @ClassName MyService
  * @Description TODO
  * @Author lazysnail
  * @Date 2024/10/17 11:42
  * @Version 1.0
  */
 @Service
 public class MyService {
     @Value("${blog.host}")
     private String host;
 ​
     @Value("${blog.email}")
     private String email;
 ​
     public void printEmail() {
         System.out.println(this.email);
     }
 }
 ​

属性配置文件

ini 复制代码
 #MyConfig.properties
 blog.host=https://lazysnailstudio.com/
 blog.email=lazy_snail@aliyun.com

主配置类

less 复制代码
 @Configuration
 @PropertySource(value = "classpath:MyConfig.properties")
 @ComponentScan(basePackages = "com.lazy.snail")
 public class AppConfig {
 ​
 }

测试类

java 复制代码
 package com.lazy.snail;
 ​
 import com.lazy.snail.service.MyService;
 import lombok.extern.slf4j.Slf4j;
 import org.junit.jupiter.api.Test;
 import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 ​
 @Slf4j
 public class SpringTest {
 ​
     @Test
     void test() {
         ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
         context.getBean(MyService.class).printEmail();
     }
 }
 ​

二、样例分析

1、new AnnotationConfigApplicationContext(AppConfig.class)

创建容器、注册内部bean定义信息、注册配置类bean定义信息

refresh之前容器中的bean定义信息:

2、refresh中invokeBeanFactoryPostProcessors

实例化内部bean(ConfigurationClassPostProcessor)

通过postProcessBeanDefinitionRegistry方法解析配置类

处理配置类AppConifg的注解

@PropertySource的处理会加载MyConfig.properties文件,然后解析其中的键值。

@ComponentScan的处理会构建扫描器,对指定包下所有类进行扫描,符合条件的注册到容器。

此案例此处会把MyService注册到容器。

MyService上有@Service注解,@Service注解中有@Component,所以MyService也会被当做配置类进行处理 。走一遍doProcessConfigurationClass方法的逻辑。

ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor,BeanDefinitionRegistryPostProcessor又继承了BeanFactoryPostProcessor,所以也具有BeanFactoryPostProcessor功能。

postProcessBeanFactory中对符合条件的配置类进行了增强处理。

invokeBeanFactoryPostProcessors结束,容器中有了MyService的bean定义信息、配置文件信息。

bean定义信息:

配置信息:

3、refresh中registerBeanPostProcessors

1、从bean定义信息集合中找到实现了BeanPostProcessor接口的beanDefinition。

org.springframework.context.annotation.internalAutowiredAnnotationProcessor

org.springframework.context.annotation.internalCommonAnnotationProcessor

这两个beanDefinition是最初构造AnnotationConfigApplicationContext时注册到容器的。

2、实例化上述两个后置处理器,然后注册到容器

实例化:

注册:

registerBeanPostProcessors结束,容器中多了两个单例对象,两个后置处理器。

单例:

后置处理器:

4、refresh中finishBeanFactoryInitialization

接下来主要看MyService的实例化过程。

preInstantiateSingletons方法会实例化容器中的单例。

得到MyService的引用后,后置处理器处理。

AutowireAnnotationBeanPostProcessor处理,找到MyService上@Value注解的属性。解析出来后添加到beanDefinition中。

开始给属性赋值

至此关于@Value的解析注入就结束了。

三、小结

1、读取解析配置文件信息,加载到容器待用。

2、实例化过程中,通过后置处理器解析@Value。

3、同样通过后置处理器,找到对应的值,赋值给对应属性。

相关推荐
yunmi_5 分钟前
安全框架 SpringSecurity 入门(超详细,IDEA2024)
java·spring boot·spring·junit·maven·mybatis·spring security
wuxuanok43 分钟前
苍穹外卖 —— 公共字段填充
java·开发语言·spring boot·spring·mybatis
洛小豆2 小时前
为什么 Integer a = 100; 不创建新对象?从编译到运行的全流程拆解
java·后端·spring
深色風信子3 小时前
SpringBoot 集成 LangChain4j 本地调用 Ollama
java·spring boot·spring·ollama·langchain4j
weixin_4196583112 小时前
Spring 的统一功能
java·后端·spring
小许学java13 小时前
Spring AI-流式编程
java·后端·spring·sse·spring ai
Lisonseekpan15 小时前
Java Caffeine 高性能缓存库详解与使用案例
java·后端·spring·缓存
SXJR16 小时前
Spring前置准备(七)——DefaultListableBeanFactory
java·spring boot·后端·spring·源码·spring源码·java开发
珹洺20 小时前
Java-Spring入门指南(二十一)Thymeleaf 视图解析器
java·开发语言·spring
EnCi Zheng20 小时前
Spring Security 最简配置完全指南-从入门到精通前后端分离安全配置
java·安全·spring