1 环境与 profile
1.1 配置 profile
@Profile 注解
指定某个 bean 属于哪一个 profile,运行时做出环境决策。
没有指定 profile 的 bean 始终都会被创建, 与激活哪个 profile 没有关系。
@Profile("dev")
@Profile("prod")
1.2 激活 profiles
Spring 提供了两个配置项定义激活哪个 profile:
- spring.profiles.active:优先
- spring.profiles.default:没有 active 则找 default
如都没有设置,则只会创建没有被 profile 修饰的 bean。
2 条件化的 bean
@Conditional
作用于 @Bean 注解修饰的方法上,通过判断指定的条件是否满足来决定是否创建该 bean。
传入注解的类一定要实现 Condition 接口,提供 matchs() 方法——如果 matches() 方法返回 true,则被 @Conditional 注解修饰的 bean 就会创建,否则对应的 bean 不会创建。
@Bean
@Conditional(MagicExistsCondition.class)
public MagicBean magicBean() {
return new MagicBean();
}
3 处理自动装配的歧义
3.1 @Primary
指定优先 bean
3.2 @Qualifier
指定 bean 的 ID
也可在 bean 和注入的地方注解相同 @Qualifier,或定义自定义 QUALIFIER
4 bean 的作用域
4.1 @Scope
Spring 中的 bean 默认都是单例,这对可变类型是非线程安全的。如果选择其他的作用域, 要使用 @Scope 注解。
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
4.2 scoped 代理
单例 bean 在加载时就会被创建,会话/请求 bean 要创建 request/session 时才会被创建。
把会话 bean 装配到单例 bean 时,应给单例 bean 装配一个会话 bean 的代理。
代理类对外暴露的接口和会话 bean 中的一样,当单例 bean 调用对应的接口时,代理采取懒解析策略,并把调用委派给实际的 session-scoped bean。设置 proxyMode 属性。
@Bean
@Scope(value=WebApplicationContext.SCOPE_SESSION,
proxyMode=ScopedProxyMode.INTERFACES)
public ShoppingCart cart() { ... }
5 运行时值注入
Spring 提供以下两种方式实现运行时注入:
- 属性占位符( Property placeholder) 。
- Spring 表达式语言( SpEL) 。
5.1 Environment
在 Spring 中解析外部值的最好方法是定义一个配置文件,然后通过 Spring 的 Environment 实例获取配置文件中的配置项的值。属性文件被加载到 Spring 的 Environment 实例中,然后通过 getProperty() 方法解析对应配置项的值。
@Configuration
@PropertySource("classpath:/app.properties")
public class ExpressiveConfig {
@Autowired
Environment env;
@Bean
public CompactDisc disc() {
return new BlankDisc(env.getProperty("disc.title"),env.getProperty("disc.artist"));
}
}
5.2 属性占位符
将属性定义到外部的属性的文件中, 并使用占位符“${ … }”将其插入到 Spring bean 中。
public BlankDisc(
@Value("${disc.title}") String title,
@Value("${disc.artist}") String artist) {
this.title = title;
this.artist = artist;
}
为了使用占位符的值,需要配置 PropertySourcesPlaceholderConfigurer
@Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
5.3 SpEL 表达式
运行时给 bean 的属性或者构造函数参数注入值
SpEL 表达式被 #{ … } 包围:
- 可以通过 bean 的 ID 引用 bean;
- 可以调用某个对象的方法或者访问它的属性;
- 支持数学、关系和逻辑操作;
- 正则表达式匹配;
- 支持集合操作