Spring高级装配术

1 Spring profile注解的使用

1.1 问题

在开发软件的时候,有一个很大的挑战就是将应用程序从一个环境迁移到另外一个环境去。很多时候数据库配置,加密算法以及外部系统集成等方面的配置都需要重新修改。这是个很大的问题

1.2 解决方案

Spring 提供了Profile注解,可以把开发环境、测试环境等许多环境统一配置到一起,然后软件部署的环境调整一下参数即可,例如数据库配置。
Java显式配置

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;
import org.springframework.jndi.JndiObjectFactoryBean;

@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();
	}
}

XML配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc"
	xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

	<beans profile = "dev">
		<jdbc:embedded-database id = "dataSource">
			<jdbc:script location = "classpath:schema.sql"/>
			<jdbc:script location = "classpath:test-data.sql"/>
		</jdbc:embedded-database>
	</beans>
	
	<beans profile = "prod">
		<jee:jndi-lookup id = "dataSource"
						jndi-name = "jdbc/myDatabase"
						resource-ref = "true" 
						proxy-interface = "javax.sql.DataSource" />
	</beans>
</beans>

激活profile
Spring在确定哪个profile处于激活状态时,需要依赖两个独立的属性:spring.profiles.active和spring.profiles.default。有多种方式来设置这两个属性,如:

  • 作为DispactcherServlet的初始化参数;
  • 作为Web应用的上下文参数;
  • 作为JNDI条目;
  • 作为环境变量;
  • 作为JVM的系统属性;
  • 在集成测试类上,使用@ActiveProfiles注解;

这里使用DispactcherServlet作为示例

<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>
	<context-param>
		<param-name>spring.profiles.default</param-name>
		<param-value>dev</param-value>
	</context-param>
	<listener>
		<listener-class>
			org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>
			org.springframework.web.servlet.DispatcherServlet
		</servlet-class>
		<init-param>
			<param-name>spring.profiles.default</param-name>
			<param-value>dev</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
</web-app>

根据上述配置,实际上默认是dev环境如果,需要切换运行环境的时候可以在代码上增加@ActiveProfiles注解
例如:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = PersistenceTestConfig.class)
@ActiveProfiles("dev")
public class PersistenceTest{
	···
}

2 条件化的bean声明

2.1 应用场景描述

假设希望一个或多个bean只有在特定条件满足时才创建就需要为bean声明条件,这样就可以在满足特定条件才创建这个bean.

2.2 例子

举个例子,假设有一个名为MagicBean的类,希望只有设置了magic环境属性的时候,Spring才会实例化这个类,如果环境没有这个属性,MagicBean将被忽略。

程序清单:

  1. MagicBean.java – bean
  2. MagicConfig.java – 显式配置类
  3. MagicExistsCondition.java – 条件

MagicBean.java

public class MagicBean {
	public void play(){
		System.out.println("测试");
	}
}

MagicConfig.java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;

public class MagicConfig {
	@Bean
	@Conditional(MagicExistsCondition.class)
	public MagicBean magicBean(){
		return new MagicBean();
	}
}

MagicExistsCondition.java

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class MagicExistsCondition implements Condition {
	@Override
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		Environment env = context.getEnvironment();
		return env.containsProperty("magic");
	}
}

编写好以上程序就可以实现在一定条件下创建bean了

猜你喜欢

转载自blog.csdn.net/weixin_37624828/article/details/84791692