springboot如何读取⾃定义properties并注⼊到bean中
⽬录
读取⾃定义properties注⼊到bean
springboot启动⽇志如下
springboot bean实例化和属性注⼊过程
springboot版本(2.0.4 RELEASE)
Bean的实例化
Bean的属性注⼊
读取⾃定义properties注⼊到bean
在使⽤springboot项⽬时,可使⽤@value的⽅式直接读取application.properties中的⽂件,但有时我们需要配置⾃定义的properties,下⾯⽅法将在springboot启动时利⽤fileinputstream读取properties⽂件中的内容,并注⼊到bean中,@Configuration注解会在springboot启动时执⾏⼀次,代码如下:package com.sh
anqis.parking.properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import t.annotation.Bean;
import t.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 = Logger(PropertiesClassLoader.class);
private Map<String, Object> versionProperties = new HashMap<>(16);
private void init(String name) {
try {
Properties properties = new Properties();
InputStream in = ClassLoader().getResourceAsStream(name + ".properties");
properties.load(in);
logger.info("加载{}.properties参数", name);
for (String keyName : properties.stringPropertyNames()) {
String value = Property(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会检查是否存在⽗⼯⼚,如果有则返回,⽅法调⽤结束
实例化bean的三种方式4) 否则,Spring会检查bean定义(BeanDefinition实例,⽤来描述Bean结果,component-scan扫描后,就是将beanDefinition实例放⼊Bean⼯⼚,此时还没有被实例化)是否有依赖关系,如果有,执⾏1)步,获取依赖的bean实例
5)否则,Spring会尝试创建这个bean实例,创建实例前,Spring会检查调⽤的构造器,并实例化该Bean,(通过wInstance(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()⽅法