欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring高级装配,Profile的使用,条件化Bean,解决歧义性

程序员文章站 2022-11-30 15:31:37
随笔,分类于 乱七八糟 下。阅读于《Spring实战 4》笔记高级装配环境 与 Profile让各个 开发环境 之间切换更加方便。使用 Profile。配置 profile bean要使用 profile,你首先要将所有不同的 bean 定义整理到一个或多个profile之中,在将应用部署到每个环境时,要确保对应的profile 处于激活(active)的状态。@Configuration@Profile("dev")public class A {@Bean("a")publi....

随笔,分类于 乱七八糟 下。阅读于《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() 方法使用 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{}

本文地址:https://blog.csdn.net/CrazyIdeas/article/details/107283226