zoukankan      html  css  js  c++  java
  • springboot 获取enviroment.Properties的几种方式

    springboot获取配置资源,主要分3种方式:@Value、 @ConfigurationProperties、Enviroment对象直接调用。
    前2种底层实现原理,都是通过第三种方式实现。

    @Value 是spring原生功能,通过PropertyPlaceholderHelper.replacePlaceholders()方法,支持EL表达式的替换。

    @ConfigurationProperties则是springboot 通过自动配置实现,并且最后通过JavaBeanBinder 来实现松绑定

    获取资源的方式

    1.1、@Value标签获取

    @Component
    @Setter@Getter
    public class SysValue {
        @Value("${sys.defaultPW}")
        private String defaultPW;
    }

    1.2、@ConfigurationProperties标签获取

    @Component
    @ConfigurationProperties(prefix = "sys")
    @Setter@Getter
    public class SysConfig {
        private String defaultPW;
    }

    1.3、直接Enviroment对象获取回去

    @Component
    public class EnvironmentValue {
        @Autowired
        Environment environment;
        private String defaultPW;
        @PostConstruct//初始化调用
        public  void init(){
            defaultPW=environment.getProperty("sys.defaultPW");
        }
    
    }

    PropertyResolver初始化与方法。

    2.1、api解释:

    Interface for resolving properties against any underlying source.
    (解析properties针对于任何底层资源的接口)

    2.2、常用实现类

    PropertySourcesPropertyResolver:配置源解析器。
    Environment:environment对象也继承了解析器。

    2.3、常用方法。

    java.lang.String getProperty(java.lang.String key):根绝 Key获取值。
    java.lang.String resolvePlaceholders(java.lang.String text)
    :替换$(....)占位符,并赋予值。(@Value 底层通过该方法实现)。

    2.4、springboot中environment初始化过程初始化PropertySourcesPropertyResolver代码。

    public abstract class AbstractEnvironment implements ConfigurableEnvironment {
    //初始化environment抽象类是,会初始化PropertySourcesPropertyResolver,
    //并将propertySources传入。
    //获取逻辑猜想:propertySources是一个List<>。
    //getProperty方法会遍历List根据key获取到value
    //一旦获取到value则跳出循环,从而实现优先级问题。
    private final ConfigurablePropertyResolver propertyResolver =
                new PropertySourcesPropertyResolver(this.propertySources);
    }

    @Value获取资源源码分析。

    解析过程涉及到(MMP看了一晚上看不懂,补贴代码了,贴个过程):
    AutowiredAnnotationBeanPostProcessor:(@Value注解解析,赋值)

    //赋值代码Autowired AnnotationBeanPostProcessor.AutowiredFieldElement.inject
    if (value != null) {
                    ReflectionUtils.makeAccessible(field);
                    field.set(bean, value);
    }

    PropertySourcesPlaceholderConfigurer:(通过配置资源替换表达式)
    PropertySourcesPropertyResolver:(根据key获取value。)

    Enviroment 对象源码解析。

    同上第三步,直接通过PropertySourcesPropertyResolver获取值。

    2.4也能发现Enviroment new的PropertyResolver是PropertySourcesPropertyResolver

    @ConfigurationProperties实现原理

    核心类:
    ConfigurationPropertiesBindingPostProcessor

    //通过自动配置,@EnableConfigurationProperties注入
    //ConfigurationPropertiesBindingPostProcessor
    @Configuration
    @EnableConfigurationProperties
    public class ConfigurationPropertiesAutoConfiguration {
    
    }

    ConfigurationPropertiesBindingPostProcessor 类解析

    //绑定数据
    private void bind(Object bean, String beanName, ConfigurationProperties annotation) {
            ResolvableType type = getBeanType(bean, beanName);
            Validated validated = getAnnotation(bean, beanName, Validated.class);
            Annotation[] annotations = (validated != null)
                    ? new Annotation[] { annotation, validated }
                    : new Annotation[] { annotation };
            Bindable<?> target = Bindable.of(type).withExistingValue(bean)
                    .withAnnotations(annotations);
            try {
                //绑定方法
                this.configurationPropertiesBinder.bind(target);
            }
            catch (Exception ex) {
                throw new ConfigurationPropertiesBindException(beanName, bean, annotation,
                        ex);
            }
    }
    
    //调用ConfigurationPropertiesBinder .bind方法。
    class ConfigurationPropertiesBinder {
      public void bind(Bindable<?> target) {
            ConfigurationProperties annotation = target
                    .getAnnotation(ConfigurationProperties.class);
            Assert.state(annotation != null,
                    () -> "Missing @ConfigurationProperties on " + target);
            List<Validator> validators = getValidators(target);
            BindHandler bindHandler = getBindHandler(annotation, validators);
            //调用getBinder方法
            getBinder().bind(annotation.prefix(), target, bindHandler);
        }
    
       //getBinder方法初始化Binder对象
       // 传入熟悉的PropertySources:也来自PropertySourcesPlaceholderConfigurer对象同@Value
       //PropertySourcesPlaceholdersResolver
       private Binder getBinder() {
            if (this.binder == null) {
                this.binder = new Binder(getConfigurationPropertySources(),
                        getPropertySourcesPlaceholdersResolver(), getConversionService(),
                        getPropertyEditorInitializer());
            }
            return this.binder;
        }
    }

    Binder.bind()方法解析

    //很深,最后通过JavaBeanBinder 来绑定数据
    //为何ConfigurationProperties无法绑定静态对象:
    //JavaBeanBinder会过滤掉静态方法
    private boolean isCandidate(Method method) {
                int modifiers = method.getModifiers();
                return Modifier.isPublic(modifiers) && !Modifier.isAbstract(modifiers)
                        && !Modifier.isStatic(modifiers)//非静态方法
                        && !Object.class.equals(method.getDeclaringClass())
                        && !Class.class.equals(method.getDeclaringClass());
    }

    本文转自:https://www.jianshu.com/p/62f0cdc435c8

  • 相关阅读:
    .Net C# ASP.Net和ADO.Net
    如何学习.Net的步骤
    PHP5.2.17版本 fgetcsv函数 读取中文bug
    大数据入门至精通视频集
    Rethinking Table Recognition using Graph Neural Networks
    GRAPH ATTENTION NETWORKS(GAT)图注意力网络
    六个步骤快速学习难以掌握的资料
    学会总结
    数据结构学习-AVL平衡树
    数据结构学习-BST二叉查找树 : 插入、删除、中序遍历、前序遍历、后序遍历、广度遍历、绘图
  • 原文地址:https://www.cnblogs.com/nizuimeiabc1/p/12173991.html
Copyright © 2011-2022 走看看