SpringBoot - yml与properties配置文件及bean赋值
SpringBoot - yml与properties配置文件及bean赋值
① SpringBoot的配置文件
SpringBoot使用一个全局的配置文件,配置文件名是固定的 :
配置文件的作用 : 修改SpringBoot自动配置的默认值(SpringBoot在底层已经配置好的属性)。
② yml 是什么?
YAML(YAML Ain’t Markup Language)
YAML A Markup Language:是一个标记语言
YAML isn’t Markup Language:不是一个标记语言;
YAML:以数据为中心,比json、xml等更适合做配置文件。
server:port:8081
③ YAML语法
YAML使用缩进表示层级关系,缩进时不允许使用Tab键,只允许使用空格。缩进的空格的数目不重要,只要相同层级的元素左侧对齐即可。
k:(空格)v;表示一对键值对,空格必须有。server:port: 8082
④ YAML值的写法
一般值有三种类型 : 字面量,即普通的值(数字,字符串,布尔);对象、map(键值对);数组(list set)。
k: v:字面直接来写;
“”:双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思
name: "zhangsan \n lisi";输出:zhangsan 换行 lisi;
‘’:单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据
name: ‘zhangsan \n lisi’; 输出:zhangsan \n lisi
k: v:在下一行来写对象的属性和值的关系;注意缩进
对象还是k: v的方式
friends:lastName: zhangsanage: 20
friends: {lastName: zhangsan,age: 18}
pets:
‐ cat
‐ dog
‐ pig
pets: [cat,dog,pig]
⑤ 使用yml为bean赋值
<!‐‐导入配置文件处理器,配置文件进行绑定就会有提示‐‐>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional>
</dependency>
@ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定。
prefix = "person":
配置文件中哪个下面的所有属性进行一一映射。
/**
* 将配置文件中配置的每一个属性的值,映射到这个组件中
* @ConfigurationProperties:告诉SpringBoot将本类中的所有属性
* 和配置文件中相关的配置进行绑定;
* prefix = "person":配置文件中哪个下面的所有属性进行一一映射
*
* 只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能;
*
*/
@Component
@ConfigurationProperties(prefix = "person")
public class Person {private String lastName;private Integer age;private Boolean boss;private Date birth;private Map<String,Object> maps;private List<Object> lists;private Dog dog;//...// 注意,@ConfigurationProperties该注解时不用再使用@Value!!!
}
server:port: 8082person:lastName: helloage: 18boss: falsebirth: 2017/12/12maps: {k1: v1,k2: 12}lists:‐ lisi‐ zhaoliudog:name: 小狗age: 12
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbooHelloworldQuickApplicationTests {@AutowiredPerson person;@Testpublic void contextLoads() {System.out.println(person);}}
(5.5)使用@ConfigurationProperties注解的同时使用@Value
@Component
@ConfigurationProperties(prefix = "person")
public class Person {@Value("${person.age}")private String lastName;//...
}
如上所示,使用@Value为属性赋值别的变量的值。测试结果表明仍然为@ConfigurationProperties该注解为lastName赋值。
⑥ properties配置文件(仍旧使用@ConfigurationProperties)
properties配置文件是以前项目中常用的配置文件,SpringBoot同样保留了该种类型的配置文件。
# idea
person.age=21
person.birth=2018/11/11
person.last-name=小明
person.boss=true
person.dog.name=dog
person.dog.age=1
person.maps.k1=v1
person.maps.k2=v2
person.lists=a,b,c
应该项目中都遇到这样的例子,读取properties文件中的中文乱码。以前解决办法就是将properties文件中的中文转换为Unicode形式,如\u822a\u6bcd。或者将其重新编码再解码。
idea中解决方法如下图:
- 将其转换为ASCII,其与Unicode是可以相互转换的。
再次测试:
⑦ @Value为bean赋值
在以前的项目中常用为bean赋值(从properties文件中获取值)的方法有两种:
<bean id="urlModel" class="com.hh.core.model.UrlModel" ><property name="url" value="${url}"></property></bean>
@Component
public class Person {/*** <bean class="Person">* <property name="lastName" value="字面量/${key}从环境变量、配置文件中获取值/#{SpEL}"></property>* <bean/>*///lastName必须是邮箱格式// @Email// 不支持JSR303校验@Value("${person.last-name}")//键必须与properties文件中的一致private String lastName;@Value("#{11*2}")//支持SpELl语法private Integer age;@Value("true")private Boolean boss;private Date birth;// @Value("${person.maps}")//不支持复杂类型封装private Map<String,Object> maps;private List<Object> lists;private Dog dog;//...
}
@Value默认从系统环境中加载属性变量。比如application.yml中配置了person.lastName属性,那么就可以使用@Value直接为Person的lastName赋值。
list: topic1,topic2,topic3
maps: "{key1: 'value1', key2: 'value2'}"
@Value("#{'${list}'.split(',')}")
private List<String> list;@Value("#{${maps}}")
private Map<String,String> maps;
⑧ @Value获取值和@ConfigurationProperties获取值比较
–person.firstName:使用标准方式
–person.first-name:大写用-
–person.first_name:大写用_
–PERSON_FIRST_NAME:
.推荐系统属性使用这种写法
上面几种写法在@ConfigurationProperties环境下都可以对应到person对象的firstName属性。@Value则必须保证取的键与properties文件中一致。
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {//lastName必须是邮箱格式
// @Value("${person.last-name}")@Emailprivate String lastName;//...
}
@Value 不支持JSR3030校验,但是支持SpELl语法,@ConfigurationProperties则相反。
如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;
如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;
那么能否在业务逻辑类中使用@ConfigurationProperties呢?
不建议使用,@ConfigurationProperties会将本类中的所有属性和配置文件中相关的配置进行绑定。尤其@ConfigurationProperties支持松散语法。
⑨ @PropertySource加载指定的配置文件
将一切配置全部写在全局配置文件中,是不可想象的。项目中不可避免存在多个配置文件。
@PropertySource就可以根据需要加载指定的配置文件(@ConfigurationProperties 默认从全局配置文件获取配置),将配置文件中的属性注入到系统环境中。
这里将person的属性配置单独写在person.properties文件中,并从全局配置文件中注释掉person的属性配置。
@PropertySource(value = {"classpath:person.properties"})
@Component
public class Person {/*** <bean class="Person">* <property name="lastName" value="字面量/${key}从环境变量、配置文件中获取值/#{SpEL}"></property>* <bean/>*///lastName必须是邮箱格式// @Email@Value("${person.last-name}")private String lastName;@Value("${person.age}")private Integer age;@Value("true")private Boolean boss;@Value("${person.birth}")private Date birth;@Value("${person.maps}")private Map<String,Object> maps;@Value("${person.lists}")private List<Object> lists;@Value("${person.dog}")private Dog dog;
为了对比person的属性从不同配置文件赋值,这里将全局配置文件中保留person.lastName属姓配置。
分析可知,默认从全局配置文件中为person赋值,这里为lastName赋值小明。
person的其他属性从person.properties文件中获取。
@PropertySource(value = {"classpath:person.properties"})
@Component
@ConfigurationProperties(prefix = "person")
public class Person {private String lastName;private Integer age;private Boolean boss;//...
}
application.properties如下图:
person.properties如下图:
测试结果如下图:
⑩ 多个配置文件同属性配置@Value取值
如果项目中不同配置文件中配置同属性,使用@Value该如何取值呢?
若将application.properties中的person.last-name注释掉,则取的为person.properties(Person类配置了@PropertySource)值。
那么是否说明,默认从全局配置文件取还是按照上下顺序依次检查呢?
(11)@ImportResource导入Spring配置文件
Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别。那么如何使用我们自己编写的配置文件呢?
<bean id="helloService" class="com.web.service.HelloService"/>
在主配置类使用ImportResource引入自定义Spring配置文件,即可获取helloService bean。
(12)SpringBoot推荐给容器中添加组件的方式
SpringBoot推荐使用配置类的方式来给容器中添加组件。如下所示:
@Configuration
public class MyAppConfig {//将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名@Beanpublic HelloService helloService(){System.out.println("配置类@Bean给容器中添加组件了...");return new HelloService();}
}
(13)配置文件占位符
除了前面说的几种方式,还可以使用占位符的方式在配置文件中为属性赋值。
person.last‐name=张三${random.uuid}
person.last‐name=张三${random.uuid}
person.age=${random.int}
person.birth=2017/12/15
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=${person.hello:hello}_dog
person.dog.age=15
(14)@PropertySource和@ConfigurationProperties以及@Value
/*** Annotation at the field or method/constructor parameter level* that indicates a default value expression for the affected argument.** <p>Typically used for expression-driven dependency injection. Also supported* for dynamic resolution of handler method parameters, e.g. in Spring MVC.** <p>A common use case is to assign default field values using* "#{systemProperties.myProp}" style expressions.** <p>Note that actual processing of the {@code @Value} annotation is performed* by a {@link org.springframework.beans.factory.config.BeanPostProcessor* BeanPostProcessor} which in turn means that you <em>cannot</em> use* {@code @Value} within* {@link org.springframework.beans.factory.config.BeanPostProcessor* BeanPostProcessor} or* {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor BeanFactoryPostProcessor}* types. Please consult the javadoc for the {@link AutowiredAnnotationBeanPostProcessor}* class (which, by default, checks for the presence of this annotation).** @author Juergen Hoeller* @since 3.0* @see AutowiredAnnotationBeanPostProcessor* @see Autowired* @see org.springframework.beans.factory.config.BeanExpressionResolver* @see org.springframework.beans.factory.support.AutowireCandidateResolver#getSuggestedValue*/
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {/*** The actual value expression: e.g. "#{systemProperties.myProp}".*/String value();}
言简意赅说一下,这个注解可以动态为属性赋值,处理过程是BeanPostProcessor!
/*** Annotation providing a convenient and declarative mechanism for adding a* {@link org.springframework.core.env.PropertySource PropertySource} to Spring's* {@link org.springframework.core.env.Environment Environment}. To be used in* conjunction with @{@link Configuration} classes.** <h3>Example usage</h3>** <p>Given a file {@code app.properties} containing the key/value pair* {@code testbean.name=myTestBean}, the following {@code @Configuration} class* uses {@code @PropertySource} to contribute {@code app.properties} to the* {@code Environment}'s set of {@code PropertySources}.** <pre class="code">* @Configuration* @PropertySource("classpath:/com/myco/app.properties")* public class AppConfig {* @Autowired* Environment env;** @Bean* public TestBean testBean() {* TestBean testBean = new TestBean();* testBean.setName(env.getProperty("testbean.name"));* return testBean;* }* }</pre>** Notice that the {@code Environment} object is @{@link* org.springframework.beans.factory.annotation.Autowired Autowired} into the* configuration class and then used when populating the {@code TestBean} object. Given* the configuration above, a call to {@code testBean.getName()} will return "myTestBean".** <h3>Resolving ${...} placeholders in {@code <bean>} and {@code @Value} annotations</h3>** In order to resolve ${...} placeholders in {@code <bean>} definitions or {@code @Value}* annotations using properties from a {@code PropertySource}, one must register* a {@code PropertySourcesPlaceholderConfigurer}. This happens automatically when using* {@code <context:property-placeholder>} in XML, but must be explicitly registered using* a {@code static} {@code @Bean} method when using {@code @Configuration} classes. See* the "Working with externalized values" section of @{@link Configuration}'s javadoc and* "a note on BeanFactoryPostProcessor-returning @Bean methods" of @{@link Bean}'s javadoc* for details and examples.** <h3>Resolving ${...} placeholders within {@code @PropertySource} resource locations</h3>** Any ${...} placeholders present in a {@code @PropertySource} {@linkplain #value()* resource location} will be resolved against the set of property sources already* registered against the environment. For example:** <pre class="code">* @Configuration* @PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties")* public class AppConfig {* @Autowired* Environment env;** @Bean* public TestBean testBean() {* TestBean testBean = new TestBean();* testBean.setName(env.getProperty("testbean.name"));* return testBean;* }* }</pre>** Assuming that "my.placeholder" is present in one of the property sources already* registered, e.g. system properties or environment variables, the placeholder will* be resolved to the corresponding value. If not, then "default/path" will be used as a* default. Expressing a default value (delimited by colon ":") is optional. If no* default is specified and a property cannot be resolved, an {@code* IllegalArgumentException} will be thrown.** <h3>A note on property overriding with @PropertySource</h3>** In cases where a given property key exists in more than one {@code .properties}* file, the last {@code @PropertySource} annotation processed will 'win' and override.** For example, given two properties files {@code a.properties} and* {@code b.properties}, consider the following two configuration classes* that reference them with {@code @PropertySource} annotations:** <pre class="code">* @Configuration* @PropertySource("classpath:/com/myco/a.properties")* public class ConfigA { }** @Configuration* @PropertySource("classpath:/com/myco/b.properties")* public class ConfigB { }* </pre>** The override ordering depends on the order in which these classes are registered* with the application context.* <pre class="code">* AnnotationConfigApplicationContext ctx =* new AnnotationConfigApplicationContext();* ctx.register(ConfigA.class);* ctx.register(ConfigB.class);* ctx.refresh();* </pre>** In the scenario above, the properties in {@code b.properties} will override any* duplicates that exist in {@code a.properties}, because {@code ConfigB} was registered* last.** <p>In certain situations, it may not be possible or practical to tightly control* property source ordering when using {@code @ProperySource} annotations. For example,* if the {@code @Configuration} classes above were registered via component-scanning,* the ordering is difficult to predict. In such cases - and if overriding is important -* it is recommended that the user fall back to using the programmatic PropertySource API.* See {@link org.springframework.core.env.ConfigurableEnvironment ConfigurableEnvironment}* and {@link org.springframework.core.env.MutablePropertySources MutablePropertySources}* javadocs for details.** @author Chris Beams* @author Juergen Hoeller* @author Phillip Webb* @since 3.1* @see PropertySources* @see Configuration* @see org.springframework.core.env.PropertySource* @see org.springframework.core.env.ConfigurableEnvironment#getPropertySources()* @see org.springframework.core.env.MutablePropertySources*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource {/*** Indicate the name of this property source. If omitted, a name will* be generated based on the description of the underlying resource.* @see org.springframework.core.env.PropertySource#getName()* @see org.springframework.core.io.Resource#getDescription()*/String name() default "";/*** Indicate the resource location(s) of the properties file to be loaded.* For example, {@code "classpath:/com/myco/app.properties"} or* {@code "file:/path/to/file"}.* <p>Resource location wildcards (e.g. **/*.properties) are not permitted;* each location must evaluate to exactly one {@code .properties} resource.* <p>${...} placeholders will be resolved against any/all property sources already* registered with the {@code Environment}. See {@linkplain PropertySource above}* for examples.* <p>Each location will be added to the enclosing {@code Environment} as its own* property source, and in the order declared.*/String[] value();/*** Indicate if failure to find the a {@link #value() property resource} should be* ignored.* <p>{@code true} is appropriate if the properties file is completely optional.* Default is {@code false}.* @since 4.0*/boolean ignoreResourceNotFound() default false;/*** A specific character encoding for the given resources, e.g. "UTF-8".* @since 4.3*/String encoding() default "";/*** Specify a custom {@link PropertySourceFactory}, if any.* <p>By default, a default factory for standard resource files will be used.* @since 4.3* @see org.springframework.core.io.support.DefaultPropertySourceFactory* @see org.springframework.core.io.support.ResourcePropertySource*/Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;}
言简意赅说明一下,该注解将制定文件中的key/value形式的属性配置注入到了Environment中!
/*** Annotation for externalized configuration. Add this to a class definition or a* {@code @Bean} method in a {@code @Configuration} class if you want to bind and validate* some external Properties (e.g. from a .properties file).* <p>* Note that contrary to {@code @Value}, SpEL expressions are not evaluated since property* values are externalized.** @author Dave Syer* @see ConfigurationPropertiesBindingPostProcessor* @see EnableConfigurationProperties*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ConfigurationProperties {/*** The name prefix of the properties that are valid to bind to this object. Synonym* for {@link #prefix()}.* @return the name prefix of the properties to bind*/@AliasFor("prefix")String value() default "";/*** The name prefix of the properties that are valid to bind to this object. Synonym* for {@link #value()}.* @return the name prefix of the properties to bind*/@AliasFor("value")String prefix() default "";/*** Flag to indicate that when binding to this object invalid fields should be ignored.* Invalid means invalid according to the binder that is used, and usually this means* fields of the wrong type (or that cannot be coerced into the correct type).* @return the flag value (default false)*/boolean ignoreInvalidFields() default false;/*** Flag to indicate that when binding to this object fields with periods in their* names should be ignored.* @return the flag value (default false)*/boolean ignoreNestedProperties() default false;/*** Flag to indicate that when binding to this object unknown fields should be ignored.* An unknown field could be a sign of a mistake in the Properties.* @return the flag value (default true)*/boolean ignoreUnknownFields() default true;/*** Flag to indicate that an exception should be raised if a Validator is available,* the class is annotated with {@link Validated @Validated} and validation fails. If* it is set to false, validation errors will be swallowed. They will be logged, but* not propagated to the caller.* @return the flag value (default true)* @deprecated as of 1.5 since validation only kicks in when {@code @Validated} is* present*/@Deprecatedboolean exceptionIfInvalid() default true;}
功能自己看源码上面的javadoc,这里需要注意的是ConfigurationPropertiesBindingPostProcessor。
ConfigurationPropertiesBindingPostProcessor源码如下:
public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProcessor,BeanFactoryAware, EnvironmentAware, ApplicationContextAware, InitializingBean,DisposableBean, ApplicationListener<ContextRefreshedEvent>, PriorityOrdered {/*** The bean name of the configuration properties validator.*/public static final String VALIDATOR_BEAN_NAME = "configurationPropertiesValidator";private static final String[] VALIDATOR_CLASSES = { "javax.validation.Validator","javax.validation.ValidatorFactory","javax.validation.bootstrap.GenericBootstrap" };private static final Log logger = LogFactory.getLog(ConfigurationPropertiesBindingPostProcessor.class);private ConfigurationBeanFactoryMetaData beans = new ConfigurationBeanFactoryMetaData();private PropertySources propertySources;private Validator validator;private volatile Validator localValidator;private ConversionService conversionService;private DefaultConversionService defaultConversionService;private BeanFactory beanFactory;private Environment environment = new StandardEnvironment();private ApplicationContext applicationContext;private List<Converter<?, ?>> converters = Collections.emptyList();private List<GenericConverter> genericConverters = Collections.emptyList();private int order = Ordered.HIGHEST_PRECEDENCE + 1;/*** A list of custom converters (in addition to the defaults) to use when converting* properties for binding.* @param converters the converters to set*/@Autowired(required = false)@ConfigurationPropertiesBindingpublic void setConverters(List<Converter<?, ?>> converters) {this.converters = converters;}/*** A list of custom converters (in addition to the defaults) to use when converting* properties for binding.* @param converters the converters to set*/@Autowired(required = false)@ConfigurationPropertiesBindingpublic void setGenericConverters(List<GenericConverter> converters) {this.genericConverters = converters;}/*** Set the order of the bean.* @param order the order*/public void setOrder(int order) {this.order = order;}/*** Return the order of the bean.* @return the order*/@Overridepublic int getOrder() {return this.order;}/*** Set the property sources to bind.* @param propertySources the property sources*/public void setPropertySources(PropertySources propertySources) {this.propertySources = propertySources;}/*** Set the bean validator used to validate property fields.* @param validator the validator*/public void setValidator(Validator validator) {this.validator = validator;}/*** Set the conversion service used to convert property values.* @param conversionService the conversion service*/public void setConversionService(ConversionService conversionService) {this.conversionService = conversionService;}/*** Set the bean meta-data store.* @param beans the bean meta data store*/public void setBeanMetaDataStore(ConfigurationBeanFactoryMetaData beans) {this.beans = beans;}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {this.beanFactory = beanFactory;}@Overridepublic void setEnvironment(Environment environment) {this.environment = environment;}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) {this.applicationContext = applicationContext;}@Overridepublic void afterPropertiesSet() throws Exception {if (this.propertySources == null) {this.propertySources = deducePropertySources();}if (this.validator == null) {this.validator = getOptionalBean(VALIDATOR_BEAN_NAME, Validator.class);}if (this.conversionService == null) {this.conversionService = getOptionalBean(ConfigurableApplicationContext.CONVERSION_SERVICE_BEAN_NAME,ConversionService.class);}}@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {freeLocalValidator();}@Overridepublic void destroy() throws Exception {freeLocalValidator();}private void freeLocalValidator() {try {Validator validator = this.localValidator;this.localValidator = null;if (validator != null) {((DisposableBean) validator).destroy();}}catch (Exception ex) {throw new IllegalStateException(ex);}}private PropertySources deducePropertySources() {PropertySourcesPlaceholderConfigurer configurer = getSinglePropertySourcesPlaceholderConfigurer();if (configurer != null) {// Flatten the sources into a single list so they can be iteratedreturn new FlatPropertySources(configurer.getAppliedPropertySources());}if (this.environment instanceof ConfigurableEnvironment) {MutablePropertySources propertySources = ((ConfigurableEnvironment) this.environment).getPropertySources();return new FlatPropertySources(propertySources);}// empty, so not very useful, but fulfils the contractlogger.warn("Unable to obtain PropertySources from "+ "PropertySourcesPlaceholderConfigurer or Environment");return new MutablePropertySources();}private PropertySourcesPlaceholderConfigurer getSinglePropertySourcesPlaceholderConfigurer() {// Take care not to cause early instantiation of all FactoryBeansif (this.beanFactory instanceof ListableBeanFactory) {ListableBeanFactory listableBeanFactory = (ListableBeanFactory) this.beanFactory;Map<String, PropertySourcesPlaceholderConfigurer> beans = listableBeanFactory.getBeansOfType(PropertySourcesPlaceholderConfigurer.class, false,false);if (beans.size() == 1) {return beans.values().iterator().next();}if (beans.size() > 1 && logger.isWarnEnabled()) {logger.warn("Multiple PropertySourcesPlaceholderConfigurer "+ "beans registered " + beans.keySet()+ ", falling back to Environment");}}return null;}private <T> T getOptionalBean(String name, Class<T> type) {try {return this.beanFactory.getBean(name, type);}catch (NoSuchBeanDefinitionException ex) {return null;}}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName)throws BeansException {ConfigurationProperties annotation = AnnotationUtils.findAnnotation(bean.getClass(), ConfigurationProperties.class);if (annotation != null) {postProcessBeforeInitialization(bean, beanName, annotation);}annotation = this.beans.findFactoryAnnotation(beanName,ConfigurationProperties.class);if (annotation != null) {postProcessBeforeInitialization(bean, beanName, annotation);}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName)throws BeansException {return bean;}@SuppressWarnings("deprecation")private void postProcessBeforeInitialization(Object bean, String beanName,ConfigurationProperties annotation) {Object target = bean;PropertiesConfigurationFactory<Object> factory = new PropertiesConfigurationFactory<Object>(target);factory.setPropertySources(this.propertySources);factory.setValidator(determineValidator(bean));// If no explicit conversion service is provided we add one so that (at least)// comma-separated arrays of convertibles can be bound automaticallyfactory.setConversionService(this.conversionService == null? getDefaultConversionService() : this.conversionService);if (annotation != null) {factory.setIgnoreInvalidFields(annotation.ignoreInvalidFields());factory.setIgnoreUnknownFields(annotation.ignoreUnknownFields());factory.setExceptionIfInvalid(annotation.exceptionIfInvalid());factory.setIgnoreNestedProperties(annotation.ignoreNestedProperties());if (StringUtils.hasLength(annotation.prefix())) {factory.setTargetName(annotation.prefix());}}try {factory.bindPropertiesToTarget();}catch (Exception ex) {String targetClass = ClassUtils.getShortName(target.getClass());throw new BeanCreationException(beanName, "Could not bind properties to "+ targetClass + " (" + getAnnotationDetails(annotation) + ")", ex);}}private String getAnnotationDetails(ConfigurationProperties annotation) {if (annotation == null) {return "";}StringBuilder details = new StringBuilder();details.append("prefix=").append(annotation.prefix());details.append(", ignoreInvalidFields=").append(annotation.ignoreInvalidFields());details.append(", ignoreUnknownFields=").append(annotation.ignoreUnknownFields());details.append(", ignoreNestedProperties=").append(annotation.ignoreNestedProperties());return details.toString();}private Validator determineValidator(Object bean) {Validator validator = getValidator();boolean supportsBean = (validator != null && validator.supports(bean.getClass()));if (ClassUtils.isAssignable(Validator.class, bean.getClass())) {if (supportsBean) {return new ChainingValidator(validator, (Validator) bean);}return (Validator) bean;}return (supportsBean ? validator : null);}private Validator getValidator() {if (this.validator != null) {return this.validator;}if (this.localValidator == null && isJsr303Present()) {this.localValidator = new ValidatedLocalValidatorFactoryBean(this.applicationContext);}return this.localValidator;}private boolean isJsr303Present() {for (String validatorClass : VALIDATOR_CLASSES) {if (!ClassUtils.isPresent(validatorClass,this.applicationContext.getClassLoader())) {return false;}}return true;}private ConversionService getDefaultConversionService() {if (this.defaultConversionService == null) {DefaultConversionService conversionService = new DefaultConversionService();this.applicationContext.getAutowireCapableBeanFactory().autowireBean(this);for (Converter<?, ?> converter : this.converters) {conversionService.addConverter(converter);}for (GenericConverter genericConverter : this.genericConverters) {conversionService.addConverter(genericConverter);}this.defaultConversionService = conversionService;}return this.defaultConversionService;}/*** {@link LocalValidatorFactoryBean} supports classes annotated with* {@link Validated @Validated}.*/private static class ValidatedLocalValidatorFactoryBeanextends LocalValidatorFactoryBean {private static final Log logger = LogFactory.getLog(ConfigurationPropertiesBindingPostProcessor.class);ValidatedLocalValidatorFactoryBean(ApplicationContext applicationContext) {setApplicationContext(applicationContext);setMessageInterpolator(new MessageInterpolatorFactory().getObject());afterPropertiesSet();}@Overridepublic boolean supports(Class<?> type) {if (!super.supports(type)) {return false;}if (AnnotatedElementUtils.hasAnnotation(type, Validated.class)) {return true;}if (type.getPackage() != null && type.getPackage().getName().startsWith("org.springframework.boot")) {return false;}if (getConstraintsForClass(type).isBeanConstrained()) {logger.warn("The @ConfigurationProperties bean " + type+ " contains validation constraints but had not been annotated "+ "with @Validated.");}return true;}}/*** {@link Validator} implementation that wraps {@link Validator} instances and chains* their execution.*/private static class ChainingValidator implements Validator {private Validator[] validators;ChainingValidator(Validator... validators) {Assert.notNull(validators, "Validators must not be null");this.validators = validators;}@Overridepublic boolean supports(Class<?> clazz) {for (Validator validator : this.validators) {if (validator.supports(clazz)) {return true;}}return false;}@Overridepublic void validate(Object target, Errors errors) {for (Validator validator : this.validators) {if (validator.supports(target.getClass())) {validator.validate(target, errors);}}}}/*** Convenience class to flatten out a tree of property sources without losing the* reference to the backing data (which can therefore be updated in the background).*/private static class FlatPropertySources implements PropertySources {private PropertySources propertySources;FlatPropertySources(PropertySources propertySources) {this.propertySources = propertySources;}@Overridepublic Iterator<PropertySource<?>> iterator() {MutablePropertySources result = getFlattened();return result.iterator();}@Overridepublic boolean contains(String name) {return get(name) != null;}@Overridepublic PropertySource<?> get(String name) {return getFlattened().get(name);}private MutablePropertySources getFlattened() {MutablePropertySources result = new MutablePropertySources();for (PropertySource<?> propertySource : this.propertySources) {flattenPropertySources(propertySource, result);}return result;}private void flattenPropertySources(PropertySource<?> propertySource,MutablePropertySources result) {Object source = propertySource.getSource();if (source instanceof ConfigurableEnvironment) {ConfigurableEnvironment environment = (ConfigurableEnvironment) source;for (PropertySource<?> childSource : environment.getPropertySources()) {flattenPropertySources(childSource, result);}}else {result.addLast(propertySource);}}}}
public class ConfigurationPropertiesBindingPostProcessor implements
BeanPostProcessor, BeanFactoryAware, EnvironmentAware,
ApplicationContextAware, InitializingBean,DisposableBean,
ApplicationListener<ContextRefreshedEvent>, PriorityOrdered {
//...
}
大概就是在bean的属性赋值、初始化前后进行的操作,具体参考博文bean的初始化和销毁过程详解。
SpringBoot - yml与properties配置文件及bean赋值相关推荐
- IDEA springboot项目中properties配置文件 {针对将对应GBK改为UTF-8并勾选转为ASCII后仍无效情况} 运行时中文乱码解决
springboot项目中properties配置文件中,运行时中文乱码情况 file encoding里边进行设置,设为utf-8并勾选转为ascii,分别在setting.setting for ...
- SpringBoot 基于配置文件给bean赋值
方式一.使用yaml文件对bean进行注入 案例: (先来两个实体类做为案例测试用) Car类 @Component public class Car {String name;String pinp ...
- SpringBoot解析yml/yaml/properties配置文件的四种方式汇总
目录 一.配置文件注入方式一@Value 二.配置文件注入方式二@ConfigurationProperties 三.自定义解析类,直接暴力读取yml配置文件 四.Spring配置文件的解析类Envi ...
- @Value直接将yml或者properties配置文件的字符串分割成数组。
将配置文件属性分割成数组. 使用注解: @Value("#{'${yourConfName}'.split(',')}") private List<String> w ...
- properties配置文件和yml配置文件互相转换
原因: 在现有的API中只找到了读取yml配置文件转化为properties形式,未找到properties格式文件,网上其他人写的测试后都有各种各样的bug,于是就自己手动重新编写一个. 目标: 1 ...
- maven 不编译jasper文件_第一个SpringBoot项目、核心配置文件properties(yml、yaml)、集成jsp...
SpringBoot简介及国内关注度 SpringBoot简介: 它用来简化 Spring 应用程序的创建和开发过程,也可以说 Spring Boot 能简化我们之前采用 SpringMVC +Spr ...
- jsp拿不到回显数据_第一个SpringBoot项目、核心配置文件properties(yml、yaml)、集成jsp...
SpringBoot简介及国内关注度 SpringBoot简介: 它用来简化 Spring 应用程序的创建和开发过程,也可以说 Spring Boot 能简化我们之前采用 SpringMVC +Spr ...
- Spring Boot 配置文件 yml与properties
原文链接:https://blog.csdn.net/qq_33524158/article/details/79600434 1.配置文件 SpringBoot使用一个全局的配置文件,配置文件名是固 ...
- SpringBoot学习:读取yml和properties文件的内容
一.在SpringBoot实现属性注入: 1).添加pom依赖jar包: 1 <!-- 支持 @ConfigurationProperties 注解 --> 2 <!-- https ...
最新文章
- 2_tabbar底部切换
- IIS的应用程序池优化方法
- QT的QWhatsThis类的使用
- 张恩民 php,php100教程_php100张恩民php视频 56课时_网站编程_寂涯网络学习基地
- Eureke服务入门就这一篇就够了
- 6. Zend_Uri
- 同花顺开放接口api_接口大师,即刻构建你的OpenAPI+开放平台
- Phase seperation 的无序结构域(IDRs)怎么预测?
- 计算机硬盘最小容量是多少,通常计算机的存储容量是多少?
- 手把手带你用Python完成一个数据分析项目,能写进简历,拿走不谢!(另送15个实战案例)...
- 拓嘉启远:拼多多前期没有流量如何补充
- 中科院计算所王永庆详解IJCAI 17录用论文:如何用注意力机制RNN进行信息传播建模?|IJCAI 2017...
- Linux之USB无线网卡开发(二)
- ntpd服务状态及日志查询方式
- 记录chrome 浏览器 本地ip 地址报 CORS 错误
- java八大数据类型_java的八大基本数据类型分别是什么?
- websocket自动重连
- .NET北京俱乐部,技术的饕餮盛宴,不枉此行
- DxO PhotoLab 2.2.2完整精华汉化版|顶级RAW数码后期软件
- uniapp GPS定位功能的实现
热门文章
- 9001.消息中间件zeroMQ
- 【MATLAB、深度学习】AlexNet及VGG神经网络在MATLAB上的应用
- STC51-串口通信
- 基于平面 marker 的 Bundle Adjustmet
- ubuntu 安装使用多版本opencv
- UDP与TCP对比,TCP保证可靠性传输的详细说明
- oracle 数据库bak文件怎么打开,Oracle数据库的参数文件备份与恢复
- php 一直运行页面,为什么浏览器关闭后PHP还会一直执行啊
- 【重难点】【Java集合 04】ArrayDeque 的使用场景、ArrayBlockingQueue
- 微信小程序|开发实战篇之三