高级组装
- 环境和 Profile 配置
- 与环境相关的
Bean
- JavaConfig:
@Profile("dev"): 只在 开发环境 创建这个 Bean
@Profile("prod"): 只在 产品环境 创建这个 Bean
- XMLConfig:
<beans profile="dev"></beans>
- Activating profiles
- 使用
spring.profiles.default: <param-name>spring.profiles.default</param-name>
- 使用
@ActiveProfiles("dev")
- 有条件性的 Bean
@Conditional(MagicExistsCondition.class)
- 接口
Condition: boolean matches(ConditionContext ctxt, AnnotatedTypeMetadata metadata)
ConditionContext
- 通过
getRegistry(). 检查 Bean 定义
- 通过
getBeanFactory() 检查 Bean 存在
- 通过
getEnvironment() 检查 环境变量的存在性
- 通过
getResourceLoader() 读取和观察资源文件内容
- 通过
getClassLoader() 加载和检查 类的存在
AnnotatedTypeMetadata
- 解决自动装载中的歧义性问题
- 多个 Bean (@Component),
NoUniqueBeanDefinitionException
- 指定 Primary Bean
@Primary
<bean id="iceCream" class="com.desserteater.IceCream" primary="true" />
- 可以指定多个 Primary Bean
@Qualifier("iceIcream")
- 在指定
@Component 的地方声明 @Qualifier("cold")
- 配合
@Autowired 使用
- 配合
@Bean 使用
- 创建多个
@Annotation
- Java 不让同一个
@Annotation 使用多次
@Qualifier public @interface Code {}
@Soft, @Crispy, @Fruity
- Bean 的作用域
- 默认全是 singletons
- Spring 提供的作用域
- Singletion
- Prototype
- Session
- 购物车:
@Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode=ScopedProxyMode.INTERFACES)
proxyMode=ScopedProxyMode.INTERFACES:
- 让 Spring 通过代理接口类来生成一个代理 Session 作用域的类
proxyMode=ScopedProxyMode.TARGET_CLASS:
- 让 Spring 使用 CGLib 生成一个具体类
XML
<bean id="card" class="com.myapp.ShoppingCart" scope="session"><aop:scoped-proxy /></bean>
<aop:scoped-proxy proxy-target-class="false" />
- Request
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
<bean id="notepad" class="com.myapp.Notepad" scope="prototype" />
- 运行时注入
- 属性 pleceholders
PropertySource("classpath:/com/soundsystem/app.properties")
env.getProperty("disc.title")
env.containsProperty("disc.title")
env.getPropertyAsClass("disc.class", CompactDisc.class)
- The Spring Expression Language
- 示例
#{ ... }
#{T(System).currentTimeMillis()}
T(): 把 java.lang.System 当做一种类型
T(java.lang.Math)
#{sgtPeppers.artist} 属性
#{artistSelector.selectArtist().toUpperCase()} 方法
#{artistSelector.selectArtist()?.toUpperCase()} 防止 NullPointerException
#{systemProperties['disc.title']}
#{3.14159} 字面量
#{'Hello'}
#{false}
- 比较
#{counter.total == 100}
#{scoreboard.score > 1000 ? "Winner!" : "Loser"}
- 正则
#{admin.email matches '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.com'}
- 集合
#{jukebox.songs[4].title}
#{'This is a test'[3]}
#{jukebox.songs.?[artist eq 'Aerosmith']}: 检查 songs 属性 artist 是否为 Aerosmith
#{jukebox.songs.^[artist eq 'Aerosmith']}: 选择第一个匹配的元素
#{jukebox.songs.$[artist eq 'Aerosmith']}: 选择最后一个匹配的元素
#{jukebox.songs.![title]}: 将 title 属性变为一个新的集合
JavaConfig
public BlankDisc( @Value("#{systemProperties['disc.title']}") String title) { this.title = title; }