Spring高级装配(二) 条件化的bean

如果你希望一个bean在特定的条件下才会出现:

  • 应用的类路径下包含特定的库时才创建
  • 只有当某个特定的bean也声明之后才会创建
  • 某个特定的环境变量设定之后才创建某个bean

在Spring 4之前,很难实现这种级别的条件化配置,但是Spring4引入了一个新的@Conditional注解,它可以用到带有@Bean注解的方法上。如果给定的条件计算结果为true,就会创建这个bean,否则的话,这个bean会被忽略。

示例:设置了magic环境属性才去实例化MagicBean

1 @Bean
2 @Conditional(MagicExistsCondition.class)    // 条件化地创建bean
3 public MagicBean magicBean() {
4     return new MagicBean();
5 }

这里的@Conditional中给定了一个Class,它指明了条件,也就是MagicCondition。

Condition接口如下:

1 public interface Condition {
2     boolean matches(ConditionContext ctxt, AnnotatedTypeMetadata metadata);
3 }

设置给@Conditional的类可以使任意实现了Condition接口的类型。如此一来,只需要提供matches( )方法的实现即可。如果matches( )方法返回为true,那么就会创建带有@Conditional注解的bean。反之则不会创建这些bean。

MagicExistsCondition的实现:

1 public class MagicExistsCondition implements Condition {
2     public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
3         Environment env = context.getEnvironment();
4         return env.containsProperty("magic");    // 检查是否有magic属性
5     }
6 }

上面的例子中只获取了Environment,ConditionContext中的内容还挺丰富的,它是一个接口:

1 public interface ConditionContext {
2     BeanDefinitionRegistry getRegistry();
3     ConfigurableListableBeanFactory getBeanFactory();
4     Environment getEnvironment();
5     ResourceLoader getResourceLoader();
6     ClassLoader getClassLoader();
7 }

通过ConditionContext,可以拿到的资源有:

  • 借助getRegistry()返回的BeanDefinitionRegistry检查bean的定义
  • 借助getBeanFactory()返回的ConfigurableListableBeanFactory检查bean是否存在(这个屌),甚至探查bean的属性
  • 借助getEnvironment()返回的Environment检查环境变量是否存在已经它的值是什么
  • 读取并探查getResourceLoader()返回的ResourceLoader所加载的资源
  • 借助getClassLoader()返回的ClassLoader加载并检查类是否存在

AnnotationedTypeMetadata则能够让我们检查带有@Bean注解的方法上还有什么其他注解。

1 public interface AnnotatedTypeMetadata {
2     boolean isAnnotated(String var1);
3     Map<String, Object> getAnnotationAttributes(String var1);
4     Map<String, Object> getAnnotationAttributes(String var1, boolean var2);
5     MultiValueMap<String, Object> getAllAnnotationAttributes(String var1);
6     MultiValueMap<String, Object> getAllAnnotationAttributes(String var1, boolean var2);
7 }

通过isAnnotated方法,我们能够判断带有@Bean注解的方法是不是还有其他特定的注解。借助其他的方法,能够检查@Bean注解的方法上其他注解的属性。

在Spring 4开始,@Profile注解进行了重构,使其基于@Conditional和Condition的实现。

在Spring 4中@Profile的实现如下:

1 @Retention(RetentionPolicy.RUNTIME)
2 @Target({ElementType.TYPE, ElementType.METHOD})
3 @Documented
4 @Conditional({ProfileCondition.class})
5 public @interface Profile {
6     String[] value();
7 }

ProfileCondition:

 1 class ProfileCondition implements Condition {
 2     @Override
 3     public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
 4         if (context.getEnvironment() != null) {
 5             MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
 6             if (attrs != null) {
 7                 for (Object value : attrs.get("value")) {
 8                     if (context.getEnvironment().acceptsProfiles(((String[]) value))) {
 9                         return true;
10                     }
11                 }
12                 return false;
13             }
14         }
15         return true;
16     }
17 }

ProfileCondition通过AnnotatedTypeMetadata得到了用于@Profile注解的所有属性。借助该信息,它会明确地检查value属性,该属性包含了bean的profile名称。然后根据ConditionContext得到的Environment来检查(借助acceptsProfiles()方法)该profile是否处于激活状态。

总结

  • @Conditional注解可以实现一个bean的条件化声明
  • Profile在Spring 4中使用@Conditional进行了重构
  • 实现条件化配置中有两个关键的接口:ConditionContext和AnnotatedTypeMetadata,在检测条件的时候起了关键作用
  • 这里没有讲在xml中如何实现条件化配置
  • 这里发现用Java来进行config还是挺爽的

原文地址:https://www.cnblogs.com/tuhooo/p/9258962.html

时间: 2024-10-18 07:59:21

Spring高级装配(二) 条件化的bean的相关文章

spring—高级装配

1. 配置profile Bean 在3.1版本中,Spring引入了bean frofile的功能.要使用profile,你首先要将所有不同的bean定义整理到一个或多个profile之中,在将应用部署到每个环境时,要确保对应的profile处于激活(active)状态. @profile("dev") @profile注解应用在类级别上.他会告诉Spring这个配置类中的bean只有在dev profile激活时才会创建.如果dev profile没有激活的话,那么带有@Bean注

002Conditional条件化创建bean

01.条件化配置bean @Bean @Conditional(MagicExistsCondition.class)---->条件化创建bean public MagicBean magicBean(){ return new MagicBean(); } 02.条件接口 public interface Condition{ boolean matches(ConditionContext ctxt, AnnotatedTypeMetadata metadata); } 03.条件类实现 p

Spring 实战-第三章-条件化的bean

在使用的时候,某些bean需要在某些特定条件化才能实例化,spring中使用的@Condition注解实现这个功能. 1.接口 package main.java.soundsystem; public interface CompactDisc { void play(); } 2.实现 package main.java.soundsystem; import org.springframework.context.annotation.Conditional; import org.spr

Spring实战(四)Spring高级装配中的bean profile

profile的原意为轮廓.剖面等,软件开发中可以译为"配置". 在3.1版本中,Spring引入了bean profile的功能.要使用profile,首先要将所有不同的bean定义整理到一个或多个profile中,在将应用部署到每个环境时,要确保对应的profile处于激活(active)状态. 1.@Profile注解应用在类上 在一个类上使用JavaConfig中的注解@Profile("xxx"),指定这个类中的bean属于某一个profile. 它告诉S

Spring In [email&#160;protected]条件化Bean

@Conditional根据某个条件来决定是否创建Bean实例 代码下载地址:http://download.csdn.net/download/poiuy1991719/9965794 创建一个Bean类: package com.bean.conditional; import org.springframework.context.annotation.Conditional; import org.springframework.stereotype.Component; @Compon

001profile条件化创建bean

01.类级别条件创建 @Configuration @Profile("dev") public class Aclass{}---->影响整个类,包括类的注解.开发环境,类中的配置才生效 02.方法级别条件创建 @Configuration poublic class AClass{ @Bean @Profile("dev")---->与@Bean一起使用,仅仅影响整个方法 public DataSource createDataSource(){ .

Spring入门学习(二)三种实例化bean的方法

前面的哪一种就是通过构造函数来实例化对象 下面我们可能用到工厂方法来视力话对象,这样我们的配置文件又该怎么配置呢 <bean name="service2" class="com.factory.ServiceFactory" factory-method="getService"></bean> 1 package com.factory; 2 3 import com.service.Service; 4 import

第三章 高级装配

Spring profile 条件化的bean声明 自动装配与歧义性 bean的作用域 Spring表达式语言 配置profile bean 在3.1版本中, Spring引入了bean profile的功能. 要使用profile, 你首先要将所有不同的bean定义整理到一个或多个profile之中, 在将应用部署 到每个环境时, 要确保对应的profile处于激活(active) 的状态. 在Java配置中, 可以使用@Profile注解指定某个bean属于哪一个profile. 例如, 在

Spring 之高级装配

[环境与Profile] 暂略 [条件化的bean] 暂略 [处理自动装配歧义性] 暂略 [ bean 的作用域] 在 @Componen . @Bean 下以及 XML 中的声明方式如下所示, @Component("LonelyHeartsClub") @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) // Singleton 作用域是默认的,Prototype 作用域需要特别声明,每次注入都会创建一个新的 Bean 实例 public