2 高级装配

Wu Jun 2018-12-18 21:53:15
06 Spring > 02 IoC

1 环境与 profile

1.1 配置 profile

@Profile 注解

指定某个 bean 属于哪一个 profile,运行时做出环境决策。

没有指定 profile 的 bean 始终都会被创建, 与激活哪个 profile 没有关系。

@Profile("dev")
@Profile("prod")

1.2 激活 profiles

Spring 提供了两个配置项定义激活哪个 profile:

如都没有设置,则只会创建没有被 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 提供以下两种方式实现运行时注入:

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 表达式被 #{ … } 包围: