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

利用 元素的 profile 的属性。中的所有 bean 都属于 指定的 profile

<beans profile="dev">
	<bean id="..." class="..." />
beans> 

是可以 进行嵌套的 ,这样 在一个 XML 文件中就可以指定多个 profile

<beans>
	
	<beans profile="dev">
		<bean id="..." class="..." />
	beans> 
	
	<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() 方法使用 ConditionContextAnnotatedTypeMetadata 对象来做决策。
  • 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{}

你可能感兴趣的:(#,Spring,笔记,java,spring,spring,boot,bean)