Spring进阶_按条件进行Bean装配
1 环境与profile
在java配置中,可以使用@Profile注解指定某个bean属于哪一个profile。@Profile注解会告诉Spring这个配置类中的bean只有在dev profile激活时才会创建,如果dev profile没有激活的话,那么带有@Bean注解的方法都会被自动忽略。
@Configuration
@Profile("dev")
public class DevelopmentfileConfig {
@Bean(destroyMethod = "shutdown")
public DataSource dataSource(){
// ...
}
}
在方法级别上使用@Profile注解,与@Bean注解一同使用
@Configuration
public class DataSourceConfig {
@Bean(destroyMethod = "shutdown")
@Profile("dev")
public DataSource embededDataSource(){
// ...
}
@Bean
@Profile("prod")
public DataSource jndiDataSource(){
// ...
}
}
激活profile
激活spring.profiles.active属性值对应的profile值, 如果没有设置, 则激活spring.profiles.default对应的值,均没设置属性值,则只会创建没有定义再profile中的bean。
- 作为DispatcherServlet的初始化参数
- 作为web应用的上下文参数
- 作为JNIDI条目
- 作为环境变量
- 作为JVM的系统属性
- 在集成测试类上,使用@ActiveProfiles注解设置
在web应用的web.xml文件中设置默认的profile的代码如下:
....
<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>dev</param-value>
</context-param>
...
<servlet>
...
<init-param>
<param-name>spring.profiles.default</param-name>
<param-value>dev</param-value>
</init-param>
...
</servlet>
环境发生变化,修改对应的即可
可以修改使用多个profile, 用逗号隔开就好
可以使用@ActiveProfiles(“dev”)激活dev profile
2 条件化的bean
假如你希望满足一定条件后,才会创建某个bean,可以使用@Conditional注解, 如果给定的条件结算结果为true,就会创建, 否则忽略。
@Bean
@Conditional(MagicExistsCondition.class)
public magicBean magicBean(){
return new MagicBean();
}
在本例中,@Conditional将会通过Condition接口进行条件对比:
public interface Condition{
boolean matches(ConditionContest xtxt, AnnotatedTypeMetadata metadata);
}
3 处理自动装配的歧义性
当一个接口有多个实现类, 而每个实现类都用@Component注解修饰, 当注入该接口时, 就会产生歧义,一般标示首选的bean(primary) @primary, 只能标志一个首选, 标志多个首选就会出现问题,实际开发情况比较少碰到这种情况。
@Component
@Primary
public class IceCream Iplents Dessert {...}
限定自动装配的bean
@Qualifier注解是使用限定符的主要方式。他可以与@Autowired和@Inject协同使用,在注入的时候指定想要注入进去的是哪个bean。
@Autowired
@Qualifier("iceCream")
public void setDessert(Dessert dessert){
this.dessert = dessert;
}
@Qualifier注解的参数就是想要注入的bean的ID。
4 bean的作用域
默认情况, Spring 应用上下文中所有的bean都是作为以单例的形式创建的, Spring定义了多种作用域,可以基于这些作用于创建bean。
- 单例(Singleton): 在整个应用中, 只创建bean一个实例
- 原型(Prototype): 每次注入或者通过Spring应用上下文获取的时候, 都会创建一个新的bean实例
- 会话(Session): 在web应用中, 为每个会话创建一个bean实例
- 请求(Request): 在web应用中, 为每个请求创建一个bean实例
使用@Scope注解切换作用域, 它可以与@Component或@Bean一起使用
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class Notepad{ ... }
使用XML来配置bean
<bean id="notepad" class="com.myapp.Notepad" scope="prototype"/>
每次注入或从Spring应用上下文中检索该bean的时候, 都会创建新的实例