Spring 周边( Environment)

参考:https://blog.csdn.net/sdlyjzh/article/details/79307239

一、体系结构

Environment是一个集成到容器之中的特殊抽象,它针对应用的环境建立了两个关键的概念:profileproperties.

profile是命名好的,其中包含了多个Bean的定义的一个逻辑集合,只有当指定的profile被激活的时候,其中的Bean才会激活。无论是通过XML定义的还是通过注解解析的Bean都可以配置到profile之中。而Environment对象的角色就是跟profile相关联,然后决定来激活哪一个profile,还有哪一个profile为默认的profile。

properties在几乎所有的应用当中都有着重要的作用,当然也可能导致多个数据源:property文件,JVM系统property,系统环境变量,JNDI,servlet上下文参数,ad-hoc属性对象,Map等。Environment对象和property相关联,然后来给开发者一个方便的服务接口来配置这些数据源,并正确解析

下面着重介绍StandardEnviroment和StandardServletEnviroment

二、Environment对properties的处理

         1.StandardEnviroment

protected void customizePropertySources(MutablePropertySources propertySources) {
		propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
		propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
	}

将 系统属性 和系统环境变量 保存到 环境中

        2.StandardServletEnviroment

protected void customizePropertySources(MutablePropertySources propertySources) {
		propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));
		propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
		if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
			propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));
		}
		super.customizePropertySources(propertySources);
	}

1.将 servletConfigInitParams 、servletContextInitParams、jndiProperties保存到环境变量中(这里只是创建了相应对象,无实际内容,真正初始化在StandardServletEnviroment.initPropertySources完成【该方法被ContextLoaderListener调用】,)

2.调用父类StandardEnviroment(将 系统属性 和系统环境变量 保存到 环境中)

三、Environment对profile的处理

StandardEnviroment和StandardServletEnviroment并没有对profile处理,但他们的父类AbstractEnvironment实现了对profile的简单操作

情景描述:

想象这样一种情况,在软件开发的过程中有开发环境和正式环境,他们使用的数据源不同,怎么才能做到无缝切换呢。也就是说怎么让Spring容器在不同的条件下注册不同的Bean。比如说生产环境和测试的环境的数据源


传统做法:

在spring3.0以前我们可以这么做,把这些不同环境的bean定义在不同的xml文件中,然后采用import标签配合PropertySourcesPlaceholderConfigurer导入不同的配置。

如下一个示例:

        <import resource="com/test/dao/dao-${test}.xml" />

上面这个示例要使之工作,需要在spring容器启动之前在System property和环境变量中添加test() 【原因如此.】

1.     带参数启动。启动程序中传入property。如下:

-Dtest=test

2.     在程序中编码添加(需在IOC加载前,或refresh容器)。

Properties pp = System.getProperties();  

pp.put(key, value)


使用profile:

以上的机制的好坏暂且不谈,但是有一点是不同的团队拥有不同的方案,而且配置文件分散,spring的profile提供统一的解决方案。

Profile是<beans>标签的一个属性,定义了一组bean属于同一个profile,如下图:

 <beans profile="qa">
       <bean id="userDao" class="com.test.dao.UserDaoImp">
       </bean>
       <bean id="userDao1" class="com.test.dao.UserDaoImp">
           <qualifier type="com.test.service.MyQualify" value="userMy" />
       </bean>
    </beans>

profile在spring内部由activeProfiles 和defaultProfiles区分,作为成员变量(Map)存在于Environment中

启用profile:

1.     使用代码

context.getEnvironment().setActiveProfiles("test");
context.refresh();

2.     启动时传入参数。

    -Dspring.profiles.active="profile1,profile2"(相当于在system.getProperty添加了k-v)


两种方式对比:

profile相比传统方式 更加细粒度。profile针对于bean,传统方式针对于bean定义文件

猜你喜欢

转载自blog.csdn.net/qq2413273056/article/details/82623803