Spring高级装配,Profile的使用,条件化Bean,解决歧义性
随笔,分类于 乱七八糟 下。阅读于《Spring实战 4》笔记
高级装配
环境 与 Profile
让各个 开发环境 之间切换更加方便。使用 Profile。
配置 profile bean
要使用 profile,你首先要将所有不同的 bean 定义整理到一个或多个profile之中,在将应用部署到每个环境时,要确保对应的profile 处于激活(active)的状态。
@Configuration
@Profile("dev")
public class A {
@Bean("a")
public void a(){}
}
-
@Profile
注解 ,指定某个bean属于哪一个 profile,括号中的 字符串 是指定哪一个 Profile- 应用在
类
上,表明类中的所有 bean 都属于指定的 profile 。 - 应用在
方法
上,和@Bean
一起使用,单独指明 一个bean 属于 那个 profile。
- 应用在
- 使用
@Profile
注解的 bean,只有在对应的 profile 处于激活 状态时 才创建。未激活 不会创建。 - 没有指定profile 的bean 始终都会被创建。
在 XML 中 配置 Profile
利用 <beans>
元素的 profile
的属性。<beans>
中的所有 bean 都属于 指定的 profile
<beans profile="dev">
<bean id="..." class="..." />
</beans>
<beans>
是可以 进行嵌套的 ,这样 在一个 XML 文件中就可以指定多个 profile
<beans>
<!-- 指定 dev profile -->
<beans profile="dev">
<bean id="..." class="..." />
</beans>
<!-- 指定 prod profile -->
<beans profile="prod">
<bean id="..." class="..." />
</beans>
</beans>
激活 Profile
需要 使用 两个 属性来 设置 那个Profile 处于激活状态。
-
spring.profiles.active
: 设置那个 profile 处于激活状态。 -
spring.profiles.default
: 在spring.profiles.active
没有设置时,使用此属性设置的值。 - 可以设置 多个 profile 文件,之间使用
,
隔开。 - 如果 两个 属性都没有设置,那就没有 激活的 Profile。
在 Spring 中有多种 方式 来 设置这两个属性。
- 作为 DispatcherServlet 的初始化参数。
- 作为 Web 应用的上下文 参数。
- 作为 JNDI 条目
- 作为 环境变量
- 作为 JVM 的系统属性
- 在集成测试类上,使用
@ActiveProfile
注解
使用 profile 进行测试
// ...
@ActiveProfiles("dev") // 指定 profile
public class Test{
// ....
}
条件化的Bean
使用 @Conditional
注解,可以用到带有 @Bean 注解的方法上。如果 给定的条件计算结果为 true,就会创建这个 bean ,否则的话,这个 bean 会被忽略。
@Bean
@Conditional(A.class) // 条件化 创建 Bean
public B newBean(){
return new B();
}
- 设置给
@Conditional
注解的类 可以是任意实现了Condition
接口的类型。
public interface Condition{
boolean matches(ConditionContext ctxt, AnnotatedTypeMetadata metadata);
}
- 如果 matches() 方法 返回 true,那么就会创建带有 @Conditional 注解的bean。
- matches() 方法使用
ConditionContext
和AnnotatedTypeMetadata
对象来做决策。 - ConditionContext 可以做到的事
- 通过
getRegistry()
返回 BeanDefinitionRegistry 检查 bean 定义 - 通过
getBeanFactory()
返回 ConfigurableListableBeanFactory 检查 bean 是否存在,甚至探查 bean 的属性。 - 通过
getEnvironment()
返回 Environment 检查 环境变量是否存在以及 它的 值。 - 通过
getResourceLoader()
返回 ResourceLoader 所加载的资源。 - 通过
getClassLoader()
返回的 ClassLoader 加载并检查类是否存在。
- 通过
- AnnotatedTypeMetadata 能够让我们检查带有 @Bean 注解的方法上还有什么其他的注解。
处理自动装配的歧义性
自动装配时 有多个 bean 可以 匹配,会产生异常。
标示首选的Bean
- 使用
@Primary
注解 把一个bean 设置为首选。能避免 自动装配时的歧义性。
@Component
@Primary // 设置 为 首选 Bean
public class A implements B{
}
- JavaConfig
@Bean
@Primary // 设置为 首选bean
public B newBean(){
return new A();
}
- xml配置
<bean id="" class="" primary="true" />
当设置 多个 首选 Bean 时,还会产生 歧义性。
限定自动装配的Bean
使用 @Qualifier
注解,进行限定
-
@Qualifier
注解,在注入时候指定想要注入进入的是那个bean。@Qualifier("要注入的Bean 的ID")
使用方式:
在创建 Bean 时,通过 @Qualifier 指定 Bean 的ID
// 在创建 Bean 时,通过 @Qualifier 指定 Bean 的ID
@Component
@Qualifier("a")
public class A implements B{}
在使用时,通过 @Qualifier 指定要使用 bean 的ID
@Autowired
@Qualifier("a")
public void setA(A a){
this.a = a;
}
自定义限定符的注解(自定义注解)
为了 解决有多个 限定条件 的情况,应为 一个 方法上 不能使用 相同的注解。
要做的就是创建一个注解,它本身要使用 @Qualifier 注解来标注,这样@Qualifier("a")
可以自定义为 @A
解决了同一个方法上 注解同名的问题。
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifer
public @Interface A{}
本文地址:https://blog.csdn.net/CrazyIdeas/article/details/107283226