Loading

Spring中的Environment接口

Environment的描述

Javadoc中的描述

Environment是表示当前应用程序正在其中运行的环境的接口,它为应用环境制定了两个关键的方面:profileproperties与属性访问有关的方法通过PropertyResolver这个父接口公开(其中,PropertyResolver这个接口主要负责解析占位符对应的值);

 

profile机制保证了仅在给定profile处于激活状态( active )时才向容器注册的BeanDefinitiion的命名逻辑组;无论是用XML定义还是通过注解定义,都可以将Bean分配给指定的profile;与配置文件相关的Environment的作用是决定当前哪些配置文件处于激活状态,以及默认情况下哪些配置文件应处于激活状态(即Environment配合profile可以完成指定模式的环境的组件装配,以及不同的配置属性注入);

 

Properties在几乎所有应用程序中都起着重要作用,并且可能源自多种来源:属性文件,JVM 系统属性,系统环境变量,JNDI,ServletContext参数,临时属性对象,Map对象等Environment与属性相关联的作用是为用户提供方便的接口,它可以用于配置属性源,并从Environment中解析属性

Environment中存放了很多propertiesproperties的来源有很多种,而properties最终的作用都是提供属性配置,或为组件注入属性值

 

ApplicationContext中管理的Bean可以注册为EnvironmentAware或使用@Inject标注在Environment上,以便直接查询profile的状态解析Properties; 但是,在大多数情况下,应用程序级 Bean不必直接与Environment交互,而是通过将${...} 属性值替换为属性占位符配置器进行属性注入(例如PropertySourcesPlaceholderConfigurer),该属性本身是EnvironmentAware,当配置了<context:property-placeholder/>时,默认情况下会使用Spring 3.1的规范注册;
  • Spring 3.1前占位符处理
    • 组件:org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
  • Spring 3.1+占位符处理
    • 组件:org.springframework.context.support.PropertySourcesPlaceholderConfigurer

Environment可以注入到组件中,用于获取当前环境激活的所有profile环境,但不推荐开发者直接使用它,而是通过占位符${...}注入属性的值;

 

Environment必须通过从所有AbstractApplicationContext子类的getEnvironment()方法返回的ConfigurableEnvironment接口完成环境对象的配置;
ConfigurableEnvironment具有可写属性的,可以修改Spring容器内部的属性值 / 数据;
 
 

Environment的体系结构

 

PropertyResolver

该接口用于配置属性的获取和解析的;

 

ConfigurableEnvironment

Configurable开头的类或接口,通常是扩展了xx属性的set方法;

可以从接口的方法定义中看到这样的方法名:setActiveProperilessetDefaultProfiles

其中getPropertySources方法获取所有的PropertySource对象;

Mutable开头的类名通常可能是一个类型的List封装,MutablePropertySources的内部是一个List;

 

StandardEnvironment

StandardEnvironment是Spring中默认使用的标准运行时环境的抽象实现;

其中StandardEnvironment类中没有getProperty方法的实现,而是在父类AbstractEnvironment中直接调用了自身组合的一个ConfigurablePropertyResolver来处理;

 

AbstractEnvironment#getProperty(java.lang.String)

 

Environment的使用

使用@Autowired获取Environment实例

查看代码
@Component
public class EnvironmentHolder {
    
    @Autowired
    Environment environment;
    
    public void printEnvironment() {
        System.out.println(environment);
    }
}

 

查看代码
 public class EnvironmentDemoApplication {
    
    public static void main(String[] args) throws Exception {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        ctx.registerBean(EnvironmentHolder.class);
        ctx.refresh();
        EnvironmentHolder environmentHolder = ctx.getBean(EnvironmentHolder.class);
        environmentHolder.printEnvironment();
    }
}

运行main方法,控制台打印出Environment的对象信息:

 

使用Environment获取配置属性的值

在resources目录下新增一个propertysource目录,创建一个demo.properties文件;

查看代码
 demo.name=a

 

查看代码
 @Component
@PropertySource("propertysource/demo.properties")
public class EnvironmentHolder {
    
    @Autowired
    Environment environment;
    
    public void printEnvironment() {
        System.out.println(Arrays.toString(environment.getDefaultProfiles()));
        System.out.println(environment.getProperty("demo.name"));
    }
}

 

查看代码
 public class EnvironmentDemoApplication {
    
    public static void main(String[] args) throws Exception {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        ctx.registerBean(EnvironmentHolder.class);
        ctx.refresh();
        EnvironmentHolder environmentHolder = ctx.getBean(EnvironmentHolder.class);
        environmentHolder.printEnvironment();
    }
}

 

运行main方法,控制台打印如下信息:

从打印的结果可以看出默认的profiles有一个默认值default,它的由来可以查看AbstractEnvironment#getDefaultProfiles

 

AbstractEnvironment#getDefaultProfiles

getDefaultProfiles方法调用了doGetDefaultProfiles

注:在Spring框架中,如果有出现一个方法是do开头,并且去掉do后能找到一个与剩余名称一样的方法,则表示的含义:不带do开头的方法一般负责前置校验处理、返回结果封装,带do开头的方法是真正执行逻辑的方法;如AbstractBeanFactory#getBean方法的底层会调用doGetBean方法来真正地执行从IOC容器中寻找bean,AbstractBeanFactory#createBean方法会调用doCreateBean方法真正地执行创建bean的逻辑;

 

AbstractEnvironment#doGetDefaultProfiles

该方法会获取框架默认的profiles,并与当前的对比,如果一致,则尝试从Environment中获取显示声明的profiles,否则取默认的deafultProfiles;

 

如果配置项spring.profiles.default没有配置,则从取默认defaultProfiles

当通过JVM启动参数指定spring.profiles.default的配置,这时候就可以覆盖默认的profiles; 

 

AbstractEnvironment#getReservedDefaultProfiles

getReservedDefaultProfiles方法取AbstractEnvironment中内置常量RESERVED_DEFAULT_PROFILE_NAME的值;

 

posted @ 2022-07-31 16:29  街头卖艺的肖邦  阅读(787)  评论(0编辑  收藏  举报