(一)spring 高级装配-@Profile

时间:2023-03-09 16:40:34
(一)spring 高级装配-@Profile

1、环境与profile

示例:数据库配置

a:通过@Bean注解,通过EmbeddedDatabaseBuilder创建数据源

@Bean(destroyMethod="shutdown")
public DataSource dataSource(){
return new EmbeddedDatabaseBuilder()
.addScript("classpath:schema.sql")
.addScript("classpath:test-data.sql")
.build();
}

这会创建一个类型为javax.sql.DataSource的bean,这个bean是如何创建出来的才是最有意思的。使用EmbeddedDatabaseBuilder会搭建一个嵌入式的Hypersonic数据库,它的模式(schema)定义在schema.sql中,测试数据则是通过test-data.sql加载的。

b:通过JndiObjectFactoryBean创建

@Bean
public DataSource dataSource(){
JndiObjectFactoryBean jndiObjectFactoryBean = new JndiOjbectFactoryBean();
jndiObjectFactoryBean.setJndiName("jdbc/myDS");
jndiObjectFactoryBean.setResourceRef(true);
jndiObjectFactoryBean.setProxyInterface(javax.sql.DataSource.class);
return (DataSource) jndiObjectFactoryBean.getObject();
}

通过JNDI获取DataSource能够让容器决定该如何创建这个DataSource,甚至包括切换为容器管理的连接池。

c:BasicDataSource 数据库配置

@Bean(destroyMethod="close")
public DataSource dataSource(){
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl("jdbc:h2:tcp://dbserver/~/test");
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUsername("sa");
dataSource.setPassword("password");
dataSource.setInitialSize(20);
dataSource.setMaxActive(30);
return dataSource;
}

  

以上三个生成的javax.sql.DataSource的bean的方法不同。在构建阶段(可能会使用Maven的profiles)确定要将哪一个配置编译到可部署的应用中。

上面的三个方式的问题在于要为每种环境重新构建应用。

引入Profile

在Java配置中,可以使用@Profile注解指定某个bean属于哪一个profile。例如可以在不同环境下配置多个profile,那个bean会被装配,则是根据那个profile被激活确定。
@Configuration
public class DataSourceConfig{ @Bean(destroyMethod="shutdown")
@Profile("dev")
public DataSource embeddedDataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:schema.sql")
.addScript("classpath:test-data-sql")
.build();
} @Bean
@Profile("prod")
public DataSource jndiDataSource(){
JndiObjectFactoryBean jndiObjectFactoryBean = new
JndiObjectFactoryBean();
jndiObjectFactoryBean.setJndiName("jdbc/myDS");
jndiObjectFactoryBean.setResourceRef(true);
jndiObjectFactoryBean.setProxyInterface(javax.sql.DataSource.class);
return (DataSource) jndiObjectFactoryBean.getObject();
}
}

  

上面通过@Profile注解,定义在不同环境下创建不同的bean。具体哪个bean被创建,根据被激活的profile确定。

激活Profile

Spring在确定哪个profile处于激活状态时,需要依赖两个独立的属性:spring.profiles.active和spring.profiles.default。
有多种方式来设置这两个属性:
  作为DispatcherServlet的初始化参数;
  作为Web应用的上下文参数;
  作为JNDI条目;
  作为环境变量;
  作为JVM的系统属性;
  在集成测试类上,使用@ActiveProfiles注解设置。

示例:

  使用DispatcherServlet的参数将spring.profiles.default设置为开发环境的profile

web.xml

<context-param>
<param-name>spring.profiles.default<param-name>
<param-value>dev</param-value>
<context-param> <servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
<servlet-class>
<init-param>
<param-name>spring.profile.default</param-name>
<param-value>dev</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

  

在spring.profiles.active和spring.profiles.default中,profile使用的都是复数形式。这意味着你可以同时激活多个profile,这可以通过列出多个profile名称,并以逗号分隔来实现。

使用profile进行测试

Spring提供了@ActiveProfiles注解,我们可以使用它来指定运行测试时要激活哪个profile。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={PersistenceTestConfig.class})
@ActiveProfiles("dev")
public class PersistenceTest{
.............
}

  @ActiveProfiles注解的参数指定到什么情况下创建bean