Spring的 @Conditional 系列注解

Spring的 @Conditional 系列注解,第1张

Preface

@Conditional 是Spring4新提供的注解

和它类似的有 @DependsOn(“beanName”) 注解, 组件依赖注解, 也就是被依赖的组件会比自身先注册到IOC容器中。

@Conditional

@Conditional({Class, Class}) 的值为 一组 Condition接口 的实现类

  • 是否满足 Condition#matches 方法 (返回true/false)
public interface Condition {
    boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}

值得注意的是, Spring本身也有很多实现类 (e.g. AllNestedConditions、AnyNestedCondition、NoneNestedConditions) 和扩展 (e.g. @ConditionalOnXxx)

XxxNestedConditions类 系列注解

这些类本身就是一个 Condition 类, 可直接作为注解 @Conditonal 的条件 (基础条件), 可用于创建复合条件 (目的).

复合条件使用静态内部类的方式实现, 条件可以是 @Conditional 也可以是 @ConditionalOnXxx;

  1. AllNestedConditions 全部匹配
  2. AnyNestedCondition 任意匹配
  3. NoneNestedConditions 全不匹配

e.g.

class DefaultWebSecurityCondition extends AllNestedConditions {

	DefaultWebSecurityCondition() {
		super(ConfigurationPhase.REGISTER_BEAN);
	}

	@ConditionalOnClass({ SecurityFilterChain.class, HttpSecurity.class })
	static class Classes {

	}

	@ConditionalOnMissingBean({ WebSecurityConfigurerAdapter.class, SecurityFilterChain.class })
	static class Beans {

	}

}
@ConditionalOnXxx 系列注解
  • @ConditionalOnBean
  • @ConditionalOnSingleCandidate
  • @ConditionalOnMissingBean

Spring 对 @Condition 做了拓展,提供了 Condition 接口的通用实现 (e.g. OnBeanCondition 类),并包装成对应的类似 @ConditonalOnBean @ConditonalOnProperty 等注解

  • @ConditionalOnProperty

配置文件 是否有对应值( havingValue, @ConditionalOnProperty 是通过 havingValue 与配置文件中的值进行判断来实现)

@ConditionalOnProperty(prefix = "spring.redis",name = "enabled", havingValue = "true")

可结合 @ConfigurationProperties(prefix=“spring.redis”) 来装配参数

@ConditionalOnXx 底层实现
  • SpringBootCondition抽象类
public abstract class SpringBootCondition implements Condition {
	public final boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		//	matches 方法
		// 通过 元数据信息 解析对应的 类、方法 名
		String classOrMethodName = getClassOrMethodName(metadata);
		try {
			/**
			 * getMatchOutcome 获取对应的 ConditionOutcome, 由子类实现
			 * ConditionOutcome 类封装了条件的匹配结果和匹配信息
			 */
			ConditionOutcome outcome = getMatchOutcome(context, metadata);
			// 匹配信息打印
			logOutcome(classOrMethodName, outcome);
			recordEvaluation(context, classOrMethodName, outcome);
			// 返回是否匹配
			return outcome.isMatch();
		}
		catch (NoClassDefFoundError ex) {
			
			// ...

		}
	}
}

SpringBootCondition 是个抽象类,实现了 Condition 接口,核心方法 match 的实现委托给了 getMatchOutcome 方法实现,其具体实现自然是由 Spring Boot 提供的各种条件类复写, 其返回的 ConditionOutcome 对象是对条件匹配结果和匹配信息的封装.

以下类仅关注 getMatchOutcome 方法实现, 他们都是SpringBootCondition子类

  • OnBeanCondition 类
  • OnPropertyCondition 类
@Import 和 @ImportResource 注解 @Import

将外部类注入到spring容器中. 在4.2之前只支持导入配置类, 在4.2之后,@Import注解支持导入普通的 java类,并将其声明成一个bean.

和@Bean的区别是:

  1. @Import 的 id 为全类名, @Bean的 id 是方法名

  2. @Import 更简单, 相比于@Bean 使用无参构造器直接 new() 更简单;

  3. 能使用 ImportSelector, 批量导入

public class MyImportSeletor implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.bidu.A","com.bidu.B"};
    }
}
@ImportResource

导入 xml 一类的配置文件:

@ImportResource(locations="classpath:applicationContext.xml")

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/876073.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存