🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
环境是抽象集成在容器中模拟应用程序环境两个关键方面配置文件和属性的抽象。 profile: 命名规则, bean命令逻辑组 Properties: 包括属性文件,JVM系统属性,系统环境变量, JNDI, servlet上下文参数,ad-hoc属性对象,等 1.31.1 Bean定义配置文件 bean definition profiles是核心容器的一种机制, 运行在不同的环境定义不同的bean. environment可以让不同的用户使用不同的东西, 包括: - 在开发中使用内存数据源, 在测试和正式环境中从JNDI使用同样的datasource - 仅在部署到性能环境中注册监视框架。 - 为客户A或客户B部署注册bean的自定义实现 以数据源的使用为例, 在测试环境中: 开发环境: /** * @Title: StandaloneDataConfig.java * @Package com.oscar999.chp13 * @Description: TODO * @author oscar999 * @date Sep 3, 2018 9:56:37 AM * @version V1.0 */ package com.oscar999.chp13; import javax.sql.DataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; /** * @ClassName: StandaloneDataConfig * @Description: TODO * @author oscar999 */ @Configuration @Profile("development") public class StandaloneDataConfig { @Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).addScript("my-schema.sql") .addScript("my-test-data.sql").build(); } } 测试或正式环境 /** * @Title: JndiDataConfig.java * @Package com.oscar999.chp13 * @Description: TODO * @author oscar999 * @date Sep 3, 2018 10:10:24 AM * @version V1.0 */ package com.oscar999.chp13; import javax.naming.Context; import javax.naming.InitialContext; import javax.sql.DataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; /** * @ClassName: JndiDataConfig * @Description: TODO * @author oscar999 */ @Configuration @Profile("production") public class JndiDataConfig { @Bean(destroyMethod="") public DataSource dataSource() throws Exception{ Context ctx = new InitialContext(); return (DataSource)ctx.lookup("java:comp/env/jdbc/datasource"); } } 两个写在同一个类里: /** * @Title: AppConfig.java * @Package com.oscar999.chp13 * @Description: TODO * @author oscar999 * @date Sep 3, 2018 10:16:39 AM * @version V1.0 */ package com.oscar999.chp13; import javax.naming.Context; import javax.naming.InitialContext; import javax.sql.DataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; /** * @ClassName: AppConfig * @Description: TODO * @author oscar999 */ @Configuration public class AppConfig { @Bean("dataSource") @Profile("development") public DataSource standaloneDataSource() { return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).addScript("my-schema.sql") .addScript("my-test-data.sql").build(); } @Bean("dataSource") @Profile("production") public DataSource jndiDataSource() throws Exception { Context ctx = new InitialContext(); return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource"); } } @Profile("production")也可以使用 @Production 替换, 定义注解接口。 /** * @Title: Production.java * @Package com.oscar999.chp13 * @Description: TODO * @author oscar999 * @date Sep 3, 2018 10:14:21 AM * @version V1.0 */ package com.oscar999.chp13; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.context.annotation.Profile; /** * @ClassName: Production * @Description: TODO * @author oscar999 */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Profile("production") public @interface Production { } 激活配置 使用哪一种配置的激活方式: AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); c ctx.getEnvironment().setActiveProfiles("development"); c ctx.register(SomeConfig.class, StandaloneDataConfig.class, JndiDataConfig.class); c ctx.refresh(); 也可以激活多个 ctx.getEnvironment().setActiveProfiles("profile1", "profile2"); 以下配置也可以 -Dspring.profiles.active="profile1,profile2" 默认配置 @Profile("default") 可以设置 spring.profiles.default 或是setDefaultProfiles()方法设置默认的。 1.13.2 PropertySource 抽象 Spring环境抽象提供了搜索可配置层级属性的操作。 ApplicationContext ctx = new GenericApplicationContext(); E Environment env = ctx.getEnvironment(); boolean containsFoo = env.containsProperty("foo"); System.out.println("Does my environment contain the 'foo' property? " + containsFoo); StandardServletEnvironment,按以下查找以下: - ServletConfig 参数,比如DispatcherServlet 的上下文 - ServletContext 参数, web.xml中context-param - JNDI 环境变量。 java:comp/env/ - JVM系统变量, 使用-D 命名行参数 - JVM系统环境- 操作系系统环境变量 也可以自己添加PropertySources  ConfigurableApplicationContext ctx = new GenericApplicationContext(); M MutablePropertySources sources = ctx.getEnvironment().getPropertySources(); s sources.addFirst(new MyPropertySource()); 1.13.3 @PropertySource @PropertySource注解提供了一个方便的添加PropertySource到Spring环境的方式。 假如app.properties包含了键值对的对应,类似: testbean.name=myTestBean @Configuration @PropertySource("classpath:/com/myco/app.properties") public class AppConfig { @Autowired Environment env; @Bean public TestBean testBean() { TestBean testBean = new TestBean(); testBean.setName(env.getProperty("testbean.name")); return testBean; } } } 任何类似${…​}在资源路径的占位符将被已经注册在环境中的值替换。 @Configuration @PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties") public class AppConfig { @Autowired Environment env; @Bean public TestBean testBean() { TestBean testBean = new TestBean(); testBean.setName(env.getProperty("testbean.name")); return testBean; } } } 1.13.4 占位符处理 一般而言,占位符元素会被JVM系统变量或是环境变量替换。但是,环境抽象集成在这个容器里, 很容易处理占位符。 <beans> <import resource="com/bank/service/${customer}-config.xml"/> </beans>