学一学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、同样通过后置处理器,找到对应的值,赋值给对应属性。

相关推荐
CodeStats5 小时前
【Spring事务】Spring事务注解 @Transactional 完整体系:从 MySQL 隔离级别到 MyBatis 原理详解
java·spring·mybatis·事务·transactional
憧憬成为java架构高手的小白12 小时前
黑马八股--spring框架学习
java·学习·spring
Nuanyt15 小时前
SSM 学习记录 第二部分 Spring整合Mybatis&Junit AOP核心概念 Spring事务管理 SpringMVC 请求与响应 Rest风格
java·spring·junit·mybatis·restful
米码收割机16 小时前
【SSM】Spring MVC_MyBatis SSM商城系统(源码+论文)【独一无二】
spring·mvc·mybatis
用户31268748772016 小时前
@Autowired 注入的是代理对象?Spring AOP 代理选择原理一次讲透
java·spring
小罗水17 小时前
第3章 从单体项目到 Spring Cloud 微服务
spring·spring cloud·微服务
Bug收容所18 小时前
12305项目学习day5
java·spring boot·redis·mysql·spring·rocketmq
lichuangcsdn18 小时前
【Spring AI 学习(三)】实现简单的对话
java·人工智能·学习·spring·spring ai
长不胖的路人甲18 小时前
Spring Bean 完整生命周期
java·spring·rpc
辰海Coding18 小时前
MiniSpring框架学习笔记-拦截器 :如何在方法前后进行拦截?
java·笔记·学习·spring·minispring