Springboot sentiment edify-@ConfigurationProperties annotation Analysis

Source: Internet
Author: User

To undertake the former Wen springboot sentiment edify [email protected] annotation analysis, this article will be based on the previous article on the use of @configurationproperties annotations

@ConfigurationProperties

This annotation is used to load the configuration file and map the corresponding values to the corresponding Java attributes, such as the following

1. Configuration Properties Specify application.properties

# user customuser.custom.username=demo_jinguser.custom.nickname=nanco[email protected]user.custom.password=demo1234user.custom.job=programmer

2. Attribute mapping class (using @configurationproperties annotations)Userproperty.java

Package Com.example.demo.bootbase;import org.springframework.boot.context.properties.configurationproperties;/** * @author Nanco * @create 2018/8/13 **/@ConfigurationProperties (prefix = "User.custom") public class UserProperty {Priv    Ate String username;    Private String nickname;    Private String Email;    private String password;    Private String job;    Public String GetUserName () {return username;    } public void Setusername (String username) {this.username = username;    } public String Getnickname () {return nickname;    } public void Setnickname (String nickname) {this.nickname = nickname;    } public String Getemail () {return email;    } public void Setemail (String email) {this.email = email;    } public String GetPassword () {return password;    } public void SetPassword (String password) {this.password = password;    } public String Getjob () {return job; } public void Setjob (String job) {this.job = job;  } @Override Public String toString () {return ' userproperty{' + ' username= ' + username + ' \ ' + ", nickname= '" + nickname + "\" + ", email=" + email + "\" + ", Passwor    D= ' + password + ' \ ' + ', job= ' + job + ' \ ' + '} '; }}

3. Attribute mapping on (using @enableconfigurationproperties annotations)Userpropertiesautoconfiguration.java

package com.example.demo.bootbase;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.context.annotation.Configuration;/** * @author nanco * @create 2018/8/13 **/@Configuration@EnableConfigurationProperties(value = UserProperty.class)public class UserPropertiesAutoConfiguration {}

4. The above annotations come into effect entrance meta-inf\spring.fatories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.demo.bootbase.UserPropertiesAutoConfiguration

5. Results test

package com.example.demo;import com.example.demo.bootbase.UserProperty;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.ApplicationContext;@SpringBootApplicationpublic class DemoSpringbootApplication {    public static void main(String[] args) {        ApplicationContext demoApplicationContext = SpringApplication.run(DemoSpringbootApplication.class, args);        UserProperty userProperty = demoApplicationContext.getBean(UserProperty.class) ;        System.out.println(userProperty);    }}

The output is as follows

......2018-08-13 14:37:05.537  INFO 17384 --- [           main] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 21474836472018-08-13 14:37:05.546  INFO 17384 --- [           main] c.e.demo.DemoSpringbootApplication       : Started DemoSpringbootApplication in 2.611 seconds (JVM running for 3.756)UserProperty{username='demo_jing', nickname='nanco', email='[email protected]', password='demo1234', job='programmer'}

The results appear as we have predicted, and the attributes are given accordingly. Below the author to carry out the analysis of the source layer to solve the binding of the small mystery

@EnableConfigurationProperties

To make the above results run successfully, you must use annotations in the corresponding startup class @EnableConfigurationProperties , let's look at their source code

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(EnableConfigurationPropertiesImportSelector.class)public @interface EnableConfigurationProperties {    /**     * Convenient way to quickly register {@link ConfigurationProperties} annotated beans     * with Spring. Standard Spring Beans will also be scanned regardless of this value.     * @return {@link ConfigurationProperties} annotated beans to register     */    Class<?>[] value() default {};}

The value property is the scanned property class, and the specified class attribute is registered to the Bean factory. Through the previous analysis can be obtained, the final analysis is through the @Import introduced by the Enableconfigurationpropertiesimportselector.class to achieve

Enableconfigurationpropertiesimportselector

View the selectimports () method of its replication directly

    private static final String[] IMPORTS = {            // 属性类注册            ConfigurationPropertiesBeanRegistrar.class.getName(),            // 属性类绑定处理            ConfigurationPropertiesBindingPostProcessorRegistrar.class.getName() };    @Override    public String[] selectImports(AnnotationMetadata metadata) {        return IMPORTS;    }

Two classes will be imported to handle the relationship of the attributes, and we analyze them in order

Configurationpropertiesbeanregistrar.class
To look directly at the way it's being replicated.

        @Override        public void registerBeanDefinitions(AnnotationMetadata metadata,                BeanDefinitionRegistry registry) {            // 读取被注解类上的EnableConfigurationProperties上的value属性并进行注入至bean工厂            getTypes(metadata).forEach((type) -> register(registry,                    (ConfigurableListableBeanFactory) registry, type));        }

The specific code is not posted out, the author here to make a small summary

  1. First read @EnableConfigurationProperties the value property on the annotated class

  2. Before injecting the class set specified in the value attribute above to the Bean factory, it is preferable to determine if the annotation has been @ConfigurationProperties modified and no error will be given.

  3. Registers the specified class collection to the Bean factory

Configurationpropertiesbindingpostprocessorregistrar
Direct view of the replication method

    @Override    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,            BeanDefinitionRegistry registry) {        if (!registry.containsBeanDefinition(                ConfigurationPropertiesBindingPostProcessor.BEAN_NAME)) {            // ConfigurationPropertiesBindingPostProcessor注册            registerConfigurationPropertiesBindingPostProcessor(registry);            // ConfigurationBeanFactoryMetadata注册            registerConfigurationBeanFactoryMetadata(registry);        }    }

The main registered two beandefinition, namely the Configurationpropertiesbindingpostprocessor class and Configurationbeanfactorymetadata class.
It seems that the specific attribute binding is the two classes to deal with, the author continues to analyze

Configurationbeanfactorymetadata

Implementation of the Postprocessbeanfactory () method in the Beanfactorypostprocessor interface class takes precedence based on the life cycle of the spring bean

    @Override    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)            throws BeansException {        this.beanFactory = beanFactory;        for (String name : beanFactory.getBeanDefinitionNames()) {            BeanDefinition definition = beanFactory.getBeanDefinition(name);            String method = definition.getFactoryMethodName();            String bean = definition.getFactoryBeanName();            if (method != null && bean != null) {                this.beansFactoryMetadata.put(name, new FactoryMetadata(bean, method));            }        }    }

It is mainly used to obtain the beandefinitions of implementing the Factorybean interface on the Bean factory and save it to the beansfactorymetadata property.

Configurationpropertiesbindingpostprocessor

Based on the spring Bean's life cycle, we first look at its afterpropertiesset () implementation method

    @Override    public void afterPropertiesSet() throws Exception {        // 获取ConfigurationBeanFactoryMetadata实体类        this.beanFactoryMetadata = this.applicationContext.getBean(                ConfigurationBeanFactoryMetadata.BEAN_NAME,                ConfigurationBeanFactoryMetadata.class);        // 创建属性绑定类        this.configurationPropertiesBinder = new ConfigurationPropertiesBinder(                this.applicationContext, VALIDATOR_BEAN_NAME);    }

And then we look at the postprocessbeforeinitialization () method

    @Override    public Object postProcessBeforeInitialization(Object bean, String beanName)            throws BeansException {        // 查找是否bean上对应的class上含有ConfigurationProperties注解        ConfigurationProperties annotation = getAnnotation(bean, beanName,                ConfigurationProperties.class);        if (annotation != null) {            // 开始绑定操作            bind(bean, beanName, annotation);        }        return bean;    }

Ok, we continue to follow the bind () method

  private void bind (Object bean, String beanname, configurationproperties annotation) {R        Esolvabletype type = Getbeantype (bean, beanname);        See if the class contains @validated annotations Validated Validated = getannotation (Bean, beanname, validated.class);  annotation[] Annotations = (validated! = null? New annotation[] {Annotation, validated}:        New annotation[] {Annotation}); class/instances/Annotations Three are bound together for the following calls bindable<?> target = Bindable.of (type). Withexistingvalue (Bean). WI        Thannotations (annotations);        try {this.configurationPropertiesBinder.bind (target);                    } catch (Exception ex) {throw new Configurationpropertiesbindexception (Beanname, bean, annotation,        ex); }    }

The final how to bind this article does not explain, involved in a lot of code, interested readers can analyze their own.
It is obvious that it will read the unified configuration of springboot such as application.properties\application.yml applied to @ConfigurationProperties annotations

Summary

If you want to use an external source's property value in Springboot, there are two methods

  1. @PropertySourceAnnotations load external sources and then @Value inject them with annotations

  2. @ConfigurationPropertiesThe annotation adornment JavaBean, whose prefix property is required, must be configured, and the internal properties of JavaBean must be consistent with the properties specified by the configuration file, and the setter method has to be configured to ensure that the property setting succeeds;
    And you must use @EnableConfigurationProperties annotations to associate the above JavaBean class with its value property

Springboot sentiment edify [email protected] annotation Analysis

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.