springboot如何读取自定义properties并注入到bean中
作者:ming199481 发布时间:2022-12-16 22:22:09
读取自定义properties注入到bean
在使用springboot项目时,可使用@value的方式直接读取application.properties中的文件,但有时我们需要配置自定义的properties,下面方法将在springboot启动时利用fileinputstream读取properties文件中的内容,并注入到bean中,@Configuration注解会在springboot启动时执行一次,代码如下:
package com.shanqis.parking.properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* 读取resource下的.properties文件,将文件中的内容封装到map中,注入到bean中方便依赖注入
*
* @author Administrator
*/
@Configuration
public class PropertiesClassLoader {
private Logger logger = LoggerFactory.getLogger(PropertiesClassLoader.class);
private Map<String, Object> versionProperties = new HashMap<>(16);
private void init(String name) {
try {
Properties properties = new Properties();
InputStream in = PropertiesClassLoader.class.getClassLoader().getResourceAsStream(name + ".properties");
properties.load(in);
logger.info("加载{}.properties参数", name);
for (String keyName : properties.stringPropertyNames()) {
String value = properties.getProperty(keyName);
if ("version".equals(name)) {
versionProperties.put(keyName, value);
}
logger.info("{}.properties---------key:{},value:{}", name, keyName, value);
}
logger.info("{}.properties参数加载完毕", name);
} catch (IOException ignored) {
}
}
@Bean(name = "versionProperties")
public Map<String, Object> commonMap() {
init("version");
return versionProperties;
}
}
springboot启动日志如下
然后在controller层或者service层等可以这样使用
/**
* 读取common.properties文件
*/
@Autowired @Qualifier("commonMap")
protected Map<String, String> commonMap;
springboot bean实例化和属性注入过程
springboot版本(2.0.4 RELEASE)
大致描述springboot中bean的实例化和属性注入过程流程
1) 在某一时刻Spring调用了Bean工厂的getBean(beanName)方法。beanName可能是simpleController,或者simpleService,simpleDao,顺序没关系(因为后面会有依赖关系的处理)。我们假设simpleController吧
2)getBean方法首先会调用Bean工厂中定义的getSingleton(beanName)方法,来判断是否存在该名字的bean单例,如果存在则返回,方法调用结束(spring默认是单例,这样可以提高效率)
3) 否则,Spring会检查是否存在父工厂,如果有则返回,方法调用结束
4) 否则,Spring会检查bean定义(BeanDefinition实例,用来描述Bean结果,component-scan扫描后,就是将beanDefinition实例放入Bean工厂,此时还没有被实例化)是否有依赖关系,如果有,执行1)步,获取依赖的bean实例
5) 否则,Spring会尝试创建这个bean实例,创建实例前,Spring会检查调用的构造器,并实例化该Bean,(通过Constructor.newInstance(args)进行实例化)
6) 实例化完成后,Spring会调用Bean工厂的populateBean方法来填充bean实例的属性,也就是自动装配。populateBean方法便是调用了BeanPostProcessor实例来完成属性元素的自动装配工作
7)在元素装配过程中,Spring会检查被装配的属性是否存在自动装配的其他属性,然后递归调用getBean方法,知道所有@Autowired的元素都被装配完成。如在装配simpleController中的simpleService属性时,发现SimpleServiceImpl实例中存在@Autowired属性simpleDao,然后调用getBean(simpleDao)方法,同样会执行1)----7)整个过程。所有可以看成一个递归过程。
8)装配完成后,Bean工厂会将所有的bean实例都添加到工厂中来。
Bean的实例化
1. 进入SpringApplication类中refreshContext()方法
2. 进入AbstractApplicationContext类中refresh()方法,找到this.finishBeanFactoryInitialization()方法,这个方法就是完成beanFactory的实例化
3. 进入AbstractApplicationContext类中finishBeanFactoryInitialization()方法,找到preInstantiateSingletons()
4. 进入DefaultListableBeanFactory类中preInstantiateSingletons()方法,找到getBean()方法
5. 进入AbstractBeanFactory类中getBean()方法,找到doGetBean()方法
6. 在AbstractBeanFactory类中doGetBean方法中,找到createBean()方法
7. 进入AbstractAutowireCapableBeanFactory类中createBean方法中,找到doCreateBean()方法
8. 在AbstractAutowireCapableBeanFactory类中doCreateBean()方法中,找到createBeanInstance()方法,看名字就知道是实例化bean的
9. 在AbstractAutowireCapableBeanFactory类createBeanInstance()方法中,找到instantiateBean()方法
10. 在AbstractAutowireCapableBeanFactory类instantiateBean()方法中,找到instantiate()方法
11. 在SimpleInstantiationStrategy类instantiate()方法中,找到instantiateClass()方法
12. 在BeanUtils类instantiateClass()方法中,可知bean的实例化是通过Constructor.newInstance()进行实例化
Bean的属性注入
1. 在AbstractAutowireCapableBeanFactory类doCreateBean()方法中,找到populateBean()方法,从名字可知是用来填充bean的
2. 在AbstractAutowireCapableBeanFactory类中populateBean()方法,找到postProcessPropertyValues()方法
3. 进入AutowiredAnnotationBeanPostProcessor类中postProcessPropertyValues()方法中,找到findAutowiringMetadata()方法,在这个方法中,如果属性中含有@Autowired注解则会递归getBean()。没有然后进入inject()方法中
4. 进入AutowiredAnnotationBeanPostProcessor类inject方法中,找到resolveDependency()方法,通过这个方法获取对应字段的值
5. 进入AutowiredAnnotationBeanPostProcessor类inject方法中,找到field.set(bean, value)方法,通过反射将值设置到属性中
来源:https://blog.csdn.net/ming199481/article/details/80500444


猜你喜欢
- 本文实例讲述了C#实现的Win32控制台线程计时器功能。分享给大家供大家参考,具体如下:在C#中提供了三种类型的计时器:1、基于 Windo
- 今天是开篇,得要吹一下算法,算法就好比程序开发中的利剑,所到之处,刀起头落。 针对现实中的排序问题,算法有七把利剑可以助你马道成功
- Swing组件中的事件处理专门用于响应用户的操作,例如,响应用户的鼠标单击、按下键盘等操作。在Swing事件处理的过程中,主要涉及三类对象:
- NumberFormat.getInstance()方法返回NumberFormat的一个实例(实际上是NumberFormat具体的一个子
- 一、 ASCII码我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串。每一个二进制位(bit)有0和1两种状态,因此八个二进制
- 1.<constant name="struts.i18n.encoding" value="UTF-8
- app中肯定是少不了与用户交互的各种dialog,下面给大家介绍几种提示框的提示。一般创建一个对话框需要经过以下几步:1、创建AlertDi
- 本文实例分享了Android获取手机系统版本等信息的方法,供大家参考,具体内容如下:第一种代码:String phoneInfo = &qu
- 最新的IDEA激活方式使用网上传统的那种输入网址的方式激活不了,使用http://idea.lanyus.com/这个网站提供的工具进行1、
- 最近一门课要求编写一个上位机串口通信工具,我基于Java编写了一个带有图形界面的简单串口通信工具,下面详述一下过程,供大家参考 ^_^一:首
- 前言相信很多人选择Spring Boot主要是考虑到它既能兼顾Spring的强大功能,还能实现快速开发的便捷。我们在Spring Boot使
- 本文实例为大家分享了java实现猜数字游戏的具体代码,供大家参考,具体内容如下随机生成0~100的数字,通过控制台输入猜测数字,输出进行提示
- 关键词IDEA 如何控制编辑左侧的功能图标 ICONIDEA 左侧的图标不见了怎么恢复1、操作步骤依次打开 File | Settings
- java 基础之final、finally和finalize的区别1.final可以修饰类,不能被继承;可以修饰方法,不能被重写;可以修饰变
- <profiles> <profile> <
- 前言fragment 可认为是一个轻量级的Activity,但不同与Activity,它是要嵌到Activity中来使用的,它用来解决设备屏
- using System;using System.Collections.Generic;using System.ComponentMo
- 一、引言那么那么那么今天来说下MP中强大的条件查询功能。本章是基于上个案例来讲的:MyBaits-Plus 快速入门案例二、具体操作首先来说
- 在开发时,我们会遇到文字过长,TextView不能完全展示,但又不想文字换行展示,这样有时会影响美观。这时我们就需要文字滚动播放,让用户可以
- 1、IO流1.流和流的分类什么是IO流?I:Input (输入)O: Ouput(输出)IO流的分类?有多种分类方式:一种方式是按照流的方向