zoukankan      html  css  js  c++  java
  • 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还是挺爽的
  • 相关阅读:
    java中的变量
    小程序获取设备信息
    小游戏学习1
    live-server
    Babel安装在本地并用webstrom由ES6转Es5
    测试目录
    使用Java模拟一个简单的Dos学生成绩管理系统:
    RabbitMQ——开源稳定的消息队列
    wpf读写app.config中的数据
    C# Arc Gis实例教程——网络链接
  • 原文地址:https://www.cnblogs.com/tuhooo/p/9258962.html
Copyright © 2011-2022 走看看