preface

For springBoot development, we use the @ConfigurationProperties annotation, which is used to convert properties or YML configuration files into beans. The @ EnableConfigurationProperties annotation is @ ConfigurationProperties annotations to take effect. If only the @ConfigurationProperties annotation is configured, the beans transformed by the Properties configuration file are not available in the IOC container, Of course, adding @Component to the class annotated with @ConfigurationProperties also makes it available for SpringBoot management.

Take a chestnut

Step 1: create a class TestConfigurationProperties

@ConfigurationProperties(prefix = "properties")
public class TestConfigurationProperties {
    private String name;

    public String getName(a) {
        return name;
    }

    public void setName(String name) {
        this.name = name; }}Copy the code

Step 2: Create the TestAutoConfiguration class

@Configuration
@EnableConfigurationProperties(TestConfigurationProperties.class)
public class TestAutoConfiguration {

    private TestConfigurationProperties testConfigurationProperties;

    public TestAutoConfiguration(TestConfigurationProperties testConfigurationProperties) {
        this.testConfigurationProperties = testConfigurationProperties;
    }

    @Bean
    public User user(a){
        User user = new User();
        user.setName(testConfigurationProperties.getName());
        returnuser; }}Copy the code

Note: You must create a parameter constructor. Step 3: Add attributes to the configuration file

properties.name=test
Copy the code

Step 4: Run and print out the User class

@RestController
@RequestMapping("/api/test")
@Slf4j
public class TestController {
    @Autowired
    TestConfigurationProperties testConfigurationProperties;

    @Autowired
    User user;

    @RequestMapping(value = "/testConfigurationProperties")
    public String testConfigurationProperties(a) {
        log.info("test testConfigurationProperties............. {}", testConfigurationProperties.getName());
        log.info("user:{}", user);
        return "SUCCESS"; }}Copy the code

Console output:

The 2019-04-21/16:11:36. 638 | | | | | | | | ^_^ | [HTTP - nio - 8088 - exec - 1] INFO com. Stone. ZPLXJJ. Controller. TestController 37 -test testConfigurationProperties............. Test the 2019-04-21/16:11:36. 639 | | | | | | | | ^_^ | [HTTP - nio - 8088 - exec - 1] INFO com. Stone. ZPLXJJ. Controller. TestController 38 - user:User(id=null, name=test)
Copy the code

@ EnableConfigurationProperties is how to load

By looking at the @ EnableConfigurationProperties annotations:

@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 {};

}
Copy the code

Through the analysis of automatic configuration can know, must be the class EnableConfigurationPropertiesImportSelector role:

private static final String[] IMPORTS = {
			ConfigurationPropertiesBeanRegistrar.class.getName(),
			ConfigurationPropertiesBindingPostProcessorRegistrar.class.getName() };

	@Override
	public String[] selectImports(AnnotationMetadata metadata) {
		return IMPORTS;
	}
Copy the code

The selectImports method returns these two classes: When is ConfigurationPropertiesBeanRegistrar and ConfigurationPropertiesBindingPostProcessorRegistrar, loaded, We only need to look at this class ConfigurationPropertiesBeanRegistrar:

public static class ConfigurationPropertiesBeanRegistrar
			implements ImportBeanDefinitionRegistrar {

		@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
			getTypes(metadata).forEach((type) -> register(registry,
					(ConfigurableListableBeanFactory) registry, type));
		}
        / / find joined the annotation @ EnableConfigurationProperties inside the value value, is a kind of class
		privateList<Class<? >> getTypes(AnnotationMetadata metadata) { MultiValueMap<String, Object> attributes = metadata .getAllAnnotationAttributes( EnableConfigurationProperties.class.getName(),false);
			returncollectClasses((attributes ! =null)? attributes.get("value")
					: Collections.emptyList());
		}

		privateList<Class<? >> collectClasses(List<? > values) {returnvalues.stream().flatMap((value) -> Arrays.stream((Object[]) value)) .map((o) -> (Class<? >) o).filter((type) ->void.class ! = type) .collect(Collectors.toList()); }// Register method: Add the @ConfigurationProperties class to the Spring container based on the found class name and type
		private void register(BeanDefinitionRegistry registry, ConfigurableListableBeanFactory beanFactory, Class
        type) {
			String name = getName(type);
			if (!containsBeanDefinition(beanFactory, name)) {
				registerBeanDefinition(registry, name, type);
			}
		}
    // Find the name of the class with the @ConfigurationProperties annotation and add a concatenation of some form
		private String getName(Class
        type) { ConfigurationProperties annotation = AnnotationUtils.findAnnotation(type, ConfigurationProperties.class); String prefix = (annotation ! =null)? annotation.prefix() :"";
			return (StringUtils.hasText(prefix) ? prefix + "-" + type.getName()
					: type.getName());
		}

		private boolean containsBeanDefinition( ConfigurableListableBeanFactory beanFactory, String name) {
			if (beanFactory.containsBeanDefinition(name)) {
				return true;
			}
			BeanFactory parent = beanFactory.getParentBeanFactory();
			if (parent instanceof ConfigurableListableBeanFactory) {
				return containsBeanDefinition((ConfigurableListableBeanFactory) parent,
						name);
			}
			return false;
		}

		private void registerBeanDefinition(BeanDefinitionRegistry registry, String name, Class
        type) {
			assertHasAnnotation(type);
			GenericBeanDefinition definition = new GenericBeanDefinition();
			definition.setBeanClass(type);
			registry.registerBeanDefinition(name, definition);
		}

		private void assertHasAnnotation(Class
        type) {
			Assert.notNull(
					AnnotationUtils.findAnnotation(type, ConfigurationProperties.class),
					() -> "No " + ConfigurationProperties.class.getSimpleName()
							+ " annotation found on '" + type.getName() + "'."); }}Copy the code

conclusion

There is also this class: ConfigurationPropertiesBindingPostProcessorRegistrar, just no analysis, looked at the source code, What it does is it assigns property values from the configuration file to the properties of the class annotated with @ConfigurationProperties. I don’t have to analyze the details, but I can read it for myself

I have also opened a wechat official account: Stonezplxjj and a personal blog: www.zplxjj.com. For more articles, please pay attention to the official account: