springboot(四)——@EnableConfigurationProperties是如何起作用的你知道吗

栏目: Java · 发布时间: 5年前

内容简介:用springboot开发的过程中,我们会用到@ConfigurationProperties注解,主要是用来把properties或者yml配置文件转化为bean来使用的,而@EnableConfigurationProperties注解的作用是@ConfigurationProperties注解生效。 如果只配置@ConfigurationProperties注解,在IOC容器中是获取不到properties配置文件转化的bean的,当然在@ConfigurationProperties加入注解的类上加

用springboot开发的过程中,我们会用到@ConfigurationProperties注解,主要是用来把properties或者yml配置文件转化为bean来使用的,而@EnableConfigurationProperties注解的作用是@ConfigurationProperties注解生效。 如果只配置@ConfigurationProperties注解,在IOC容器中是获取不到properties配置文件转化的bean的,当然在@ConfigurationProperties加入注解的类上加@Component也可以使交于springboot管理。

举个栗子

第一步:创建一个类TestConfigurationProperties

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
复制代码

注意:得加上set和get方法

第二步:创建TestAutoConfiguration类

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

    private TestConfigurationProperties testConfigurationProperties;

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

    @Bean
    public User user(){
        User user = new User();
        user.setName(testConfigurationProperties.getName());
        return user;
    }
}
复制代码

注意:得创建一个有参构造方法

第三步:配置文件加入属性

properties.name=test
复制代码

第四步:跑一下,打印出User这个类

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

    @Autowired
    User user;

    @RequestMapping(value = "/testConfigurationProperties")
    public String testConfigurationProperties() {
        log.info("test testConfigurationProperties.............{}", testConfigurationProperties.getName());
        log.info("user:{}", user);
        return "SUCCESS";
    }
}
复制代码

控制台输出:

2019-04-21/16:11:36.638||||||||^_^|[http-nio-8088-exec-1] INFO  com.stone.zplxjj.controller.TestController 37 - test testConfigurationProperties.............test
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)
复制代码

@EnableConfigurationProperties是怎么加载的

通过查看@EnableConfigurationProperties的注解:

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

}
复制代码

通过分析自动配置可以知道,肯定是这个类EnableConfigurationPropertiesImportSelector起的作用:

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

	@Override
	public String[] selectImports(AnnotationMetadata metadata) {
		return IMPORTS;
	}
复制代码

selectImports方法返回了这两个类:ConfigurationPropertiesBeanRegistrar和ConfigurationPropertiesBindingPostProcessorRegistrar,是何时加载的,我们只需要看这个类ConfigurationPropertiesBeanRegistrar即可:

public static class ConfigurationPropertiesBeanRegistrar
			implements ImportBeanDefinitionRegistrar {

		@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata,
				BeanDefinitionRegistry registry) {
			getTypes(metadata).forEach((type) -> register(registry,
					(ConfigurableListableBeanFactory) registry, type));
		}
        //找到加入这个注解@EnableConfigurationProperties里面的value值,其实就是类class
		private List<Class<?>> getTypes(AnnotationMetadata metadata) {
			MultiValueMap<String, Object> attributes = metadata
					.getAllAnnotationAttributes(
							EnableConfigurationProperties.class.getName(), false);
			return collectClasses((attributes != null) ? attributes.get("value")
					: Collections.emptyList());
		}

		private List<Class<?>> collectClasses(List<?> values) {
			return values.stream().flatMap((value) -> Arrays.stream((Object[]) value))
					.map((o) -> (Class<?>) o).filter((type) -> void.class != type)
					.collect(Collectors.toList());
		}
      //注册方法:根据找到的类名name和type,将加入注解@ConfigurationProperties的类加入spring容器里面
		private void register(BeanDefinitionRegistry registry,
				ConfigurableListableBeanFactory beanFactory, Class<?> type) {
			String name = getName(type);
			if (!containsBeanDefinition(beanFactory, name)) {
				registerBeanDefinition(registry, name, type);
			}
		}
    //找到加入注解@ConfigurationProperties的类的名称,加入一定格式的拼接
		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() + "'.");
		}

	}
复制代码

结语

另外还有这个类:ConfigurationPropertiesBindingPostProcessorRegistrar,刚刚没有分析,看了下源码,其实他做的事情就是将配置文件当中的属性值赋予到加了@ConfigurationProperties的注解的类的属性上,具体就不分析了,有兴趣自己可以阅读,入口知道了,就简单了

本人也开通了微信公众号:stonezplxjj,更多文章欢迎关注公众号:

springboot(四)——@EnableConfigurationProperties是如何起作用的你知道吗

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Is Parallel Programming Hard, And, If So, What Can You Do About

Is Parallel Programming Hard, And, If So, What Can You Do About

Paul E. McKenney

The purpose of this book is to help you understand how to program shared-memory parallel machines without risking your sanity.1 By describing the algorithms and designs that have worked well in the pa......一起来看看 《Is Parallel Programming Hard, And, If So, What Can You Do About 》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试