Spring Environment抽象

理解Spring Environment抽象

  • 统一的配置属性管理

Spring Framework3.1开始引入Environment抽象,它统一Spring配置属性的存储,包括占位符处理和类型转换,不仅完整地替换PropertyPlaceholderConfigurer,而且还支持更丰富的配置属性源(PropertySource)

  • 条件化Spring Bean装配管理

通过Environment Profiles信息,帮助Spring容器提供条件化地装配Bean

Spring Environment接口使用场景

  • 用于属性占位符处理
  • 用于转换Spring配置属性类型
  • 用于存储Spring配置属性源(PropertySource)
  • 用于Profiles状态的维护

Environment占位符处理

  • Spring3.1前占位符处理
    • 组件:org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
    • 接口:org.springframework.util.StringValueResolver
  • Spring3.1+占位符处理
    • 组件:org.springframework.context.support.PropertySourcesPlaceholderConfigurer
    • 接口:org.springframework.beans.factory.config.EmbeddedValueResolver

理解条件配置Spring Profiles

  • Spring3.1条件配置

    • API:org.springframework.core.env.ConfigurableEnvironment
      • 修改:addActiveProfile(String)、setActiveProfiles(String…)、setDefaultActiveProfiles(String…)
      • 获取:getActiveProfiles()和getDefaultProfiles()
      • 匹配:acceptsProfiles(String…)和acceptsProfiles(Profiles)
    • 注解:@org.springframework.context.annotation.Profile
  • 基于Spring4重构@Profile Condition接口

    • org.springframework.context.annotation.ProfileCondition

依赖注入Environment

  • 直接依赖注入
    • 通过EnvironmentAware接口回调
    • 通过@Autowire注入Environment
  • 间接依赖注入
    • 通过ApplicationContextAware接口回调
    • 通过@Autowire注入ApplicationContext

依赖查找Environment

  • 直接依赖查找
    • 通过org.springframework.context.ConfigurableApplicationContext#ENVIRONMENT_BEAN_NAME
  • 间接依赖查找
    • 通过org.springframework.context.ConfigurableApplicationContext#getEnvironment

依赖注入@Value

依赖注入@Value实现:AutowiredAnnotationBeanPostProcessor

Spring类型转换在Environment中的运用

  • 底层实现:org.springframework.core.env.PropertySourcesPropertyResolver
    • 核心方法:convertValueIfNecessary(Object,Class)

Spring类型转换在@Value中的运用

  • 底层实现:org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
    • org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency
  • 底层服务:org.springframework.beans.TypeConverter
    • 默认实现:org.springframework.beans.TypeConverterDelegate
      • java.beans.PropertyEditor
      • org.springframework.core.convert.ConversionService

Spring配置属性源PropertySource

  • API

    • 单配置属性源-org.springframework.core.env.PropertySource
    • 多配置属性源-org.springframework.core.env.PropertySources
  • 注解

    • 单配置属性源-@org.springframework.context.annotation.PropertySource
    • 多配置属性源-@org.springframework.context.annotation.PropertySources
  • 关联

    • 存储对象-org.springframework.core.env.MutablePropertySources
    • 关联方法-org.springframework.core.env.ConfigurableEnvironment#getPropertySources

Spring内建的配置属性源

PropertySource类型说明
org.springframework.core.env.CommandLinePropertySource命令行配置属性源
org.springframework.jndi.JndiPropertySourceJNDI配置属性源
org.springframework.core.env.PropertiesPropertySourceProperties配置属性源
org.springframework.web.context.support.ServletConfigPropertySourceServlet配置属性源
org.springframework.web.context.support.ServletContextPropertySourceServletContext配置属性源
org.springframework.core.env.SystemEnvironmentPropertySource环境变量配置属性源
org.springframework.core.env.MapPropertySourceMap配置属性源

基于注解扩展Spring配置属性源

@org.springframework.context.annotation.PropertySource实现原理

  • 入口-org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass
    • org.springframework.context.annotation.ConfigurationClassParser#processPropertySource
  • 4.3新增语义
    • 配置属性字符编码-encoding
    • org.springframework.core.io.support.PropertySourceFactory
  • 适配对象-org.springframework.core.env.CompositePropertySource

基于API扩展Spring配置属性源

	public static void main(String[] args) {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        // 注册 Configuration Class
        context.register(EnvironmentPropertySourceChangeDemo.class);

        // 在 Spring 应用上下文启动前,调整 Environment 中的 PropertySource
        ConfigurableEnvironment environment = context.getEnvironment();
        // 获取 MutablePropertySources 对象
        MutablePropertySources propertySources = environment.getPropertySources();
        // 动态地插入 PropertySource 到 PropertySources 中
        Map<String, Object> source = new HashMap<>();
        source.put("user.name", "小马哥");
        MapPropertySource propertySource = new MapPropertySource("first-property-source", source);
        propertySources.addFirst(propertySource);

        // 启动 Spring 应用上下文
        context.refresh();

        source.put("user.name", "007");

        EnvironmentPropertySourceChangeDemo environmentPropertySourceChangeDemo = context.getBean(EnvironmentPropertySourceChangeDemo.class);

        System.out.println(environmentPropertySourceChangeDemo.userName);

        for (PropertySource ps : propertySources) {
            System.out.printf("PropertySource(name=%s) 'user.name' 属性:%s\n", ps.getName(), ps.getProperty("user.name"));
        }

        // 关闭 Spring 应用上下文
        context.close();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值