1 @profile
注解
1.1 JavaConfig 配置
@profile
注解在 Spring 中用于根据 环境 决定某个 bean 是否应该被创建。
通常的,@profile
注释应用在类级别上,如下代码,它会告诉 Spring 这个名叫 DevelopmentProfileConfig
配置类中的 bean 只有在 dev
profile 激活的时候才会创建。
@Configuration
@Profile("dev")
public class DevelopmentProfileConfig {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder();
}
}
1.2 XML 配置
XML 配置使用 @Profile
注解则是在 <beans>
元素中声明属性 profile
,如:
<beans profile="dev" ...>
....
</beans>
1.3 激活 profile
Spring 在确定哪个 profile 处于激活状态的时候,需要依赖两个独立的属性:
spring.profiles.active
spring.profiles.default
即如果没有设置 active
值时,默认会取 default
值,如果二者都没有设置,那么就没有激活的 profile,因此只会创建那些没有定义在 profile 中的bean。
有多种方式来设置这两个属性,以下举出常用的两种形式:
- 作为
DispatcherServerlet
的初始化参数: - 作为 Web 应用的上下文参数
即在 Web 应用中的 web.xml
文件中设置 profile,在该 xml 文件中添加以下元素:
<!-- 为上下文设置默认的 profile -->
<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>dev</param-value>
</context-param>
<!-- .... -->
<!-- 为 Servlet 设置默认的 profile -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<!-- 为 Servlet 设置默认的 profile -->
<init-param>
<param-name>spring.profiles.default</param-name>
<param-value>dev</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
2 @Conditional
@Conditional
注释给定一个 class,它指明了条件,声明了此注释的 bean 。
该 class 实质是一个 Condition
接口的实现,Condition
接口实现只需提供 matches()
方法的实现即可,如果 matches
方法返回 true
,那么就会创建带有 @Confitional
注解的 bean,否则将不会创建该 bean。
matches
方法有两个参数,分别是 ConditionContext
以及 AnnotatedTypeMetadata
。
ConditionContext
是一个接口,它有以下几个重要的方法:
getRegistry()
返回BeanDefinitionRegistry
检查 bean 定义getBeanFactory()
返回ConfigurableListableBeanFactory
检查 bean 是否存在,甚至探查 bean 的属性getEnvironment()
返回的 Environment 检查环境变量是否存在以及它的值是什么getResourceLoader()
返回的 ResourceLoader 所加载的资源getClassLoader()
返回的 ClassLoader 加载并检查类是否存在
AnnotatedTypeMetadata
同样是一个接口,它能够检查带有 @Bean
注解的方法上还有什么其他的注解。
eg:
public class MagicExistCondition implements Condition {
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment env = context.getEnvironment();
return env.containsProperty("magic");
}
}
3 @ Qualifier
使用 @Autowired
注释实现自动装配的时候,默认的是按照类型进行自动装配,如果自动装配的时候出现多个相同的类型,就会报错了,此时可以使用 @Qualifier
注解进行依赖 ID 而不是类型的注入:
@Autowired
@Qualifier("iceCream")
public void setDessert(Dessert dessert) {
this.dessert = dessert;
}
3.1 创建自定义的限定符
自动装配的时候,按照的 ID 是 bean 声明时候的类名,如果想要自定义 ID,可以在声明组件 bean 的时候添加 @Qualifier
注解
@Component
@Qualifier("iceCream")
public class IceCream {}
4 @Scope
在默认的情况下,Spring 引用上下文所有 bean 都是作为单利的形式创建的,也就是说,不管给定的 bean 被注入到其它的 bean 多少次,每次注入的都是同一个实例。
Spring 定义了多种作用域,可以基于这些作用域创建 bean,包括:
- 单例(Singleton):在整个应用中,只创建一个实例
- 原型(Prototype):每次注入或通过 Spring 应用上下文获取的时候,都会创建一个 bean 的实例
- 会话(Session):在 Web 应用中,为每个会话创建一个 bean 实例
- 请求(Request):在 Web 应用中,为每个请求创建一个 bean 实例
eg:
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class Notepad {
....
}
5 @PropertySource
在 Spring 中,处理外部值得最简单方式就是声明属性源并通过 Spring 的 Environment 来检索属性。
@PropertySource
注解用于声明属性源,再通过 Environment 实例获取相应的属性值。
eg:
@Configuration
@PropertySource("classpath:/top/seiei/app.properties")
public class ExpresssiveConfig {
@Autowired
Environment env;
@Bean
public BlankDisc disc() {
return new BlankDisc(
env.getProperty("disc.title"),
env.getProperty("disc.artist")
);
}
}