Spring注解驱动开发学习总结3:组件注册之@Conditional详解

1、使用@Conditional 按照条件注册bean

使用@Conditional 注解,可以按照一定的条件进行判断,满足条件的话,才会给容器中注册bean。在springboot框架中大量地使用了该注解
1、查看@Conditional 注解,可以看到该注解的参数value,可以传一个实现了Condition接口的实现类的数组;

public @interface Conditional {
	Class<? extends Condition>[] value();
}

2、接着查看下Condition接口,可以看到只需要实现它的一个方法matches,用来判断条件是否满足。
入参共有2个参数:
1)ConditionContext:判断条件能使用的上下文环境(包括ioc的beanfactory,类加载器,环境信息,bean定义的注册类)
2)AnnotatedTypeMetadata:注释信息
基于上面的两个参数里的信息,就可以进行来做判断,是否需要注册该实例的bean了。

public interface Condition {
	/**
	 * Determine if the condition matches.
	 * @param context the condition context
	 * @param metadata metadata of the {@link org.springframework.core.type.AnnotationMetadata class}
	 * or {@link org.springframework.core.type.MethodMetadata method} being checked.
	 * @return {@code true} if the condition matches and the component can be registered
	 * or {@code false} to veto registration.
	 */
	boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}

接着上一篇文章,继续在容器中注册id为bill的person实例,和id为linus的person实例。
当系统是Windows的时候,bill的person实例就注册进容器中;
当系统是linux的时候,linus的person就注册进实例中。
下面以这个小功能进行举例。

1.1 构建自定义Condition

1)构建判断是否是Linux系统的自定义条件实现类:com/example/condition/LinuxCondition.java
我们可以看到,从context可以获得很多信息,可以供给我们使用判断:

  1. 可以获取到ioc使用的beanfactory;
  2. 可以获取到类加载器
  3. 可以获取到当前环境信息
  4. 可以获取到bean定义的注册类
package com.example.condition;

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class LinuxCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // 1、可以获取到ioc使用的beanfactory
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();

        // 2、可以获取到类加载器
        ClassLoader classLoader = context.getClassLoader();

        // 3、可以获取到当前环境信息
        Environment environment = context.getEnvironment();

        // 4、可以获取到bean定义的注册类
        BeanDefinitionRegistry registry = context.getRegistry();

        // 通过environment获取当前系统
        String property = environment.getProperty("os.name");
        if (property.toUpperCase().contains("LINUX")) {
            return true;
        }
        return false;
    }
}

1)构建判断是否是Windows系统的自定义条件实现类:com/example/condition/WindowsCondition.java

package com.example.condition;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // 可以获取到当前环境信息
        Environment environment = context.getEnvironment();

        // 通过environment获取当前系统,如果包含windows,那么就不是linux系统
        String property = environment.getProperty("os.name");
        if (property.toUpperCase().contains("WINDOWS")) {
            return true;
        }
        return false;
    }
}

1.2 按条件注入person实例

继续在上一篇博文的配置类MainConfig2中,继续添加两个person实例,只是这2个实例上面分别添加了对应的@Conditional注解。

当系统是Windows的时候,bill的person实例就注册进容器中;
当系统是linux的时候,linus的person就注册进实例中。

package com.example.config;

import com.example.bean.Person;
import com.example.condition.LinuxCondition;
import com.example.condition.WindowsCondition;
import org.springframework.context.annotation.*;

@Configuration
public class MainConfig2 {
    @Conditional(WindowsCondition.class)
    @Bean("bill")
    public Person person01() {
        return new Person("Bill Gates", 62);
    }

    @Conditional(LinuxCondition.class)
    @Bean("linus")
    public Person PERSON02() {
        return new Person("Linus", 48);
    }
}

1.3 构建测试方法

构建测试方法:testConditonal()。
测试方法中会打印当前系统的名称,并且会打印最终注入的person实例名称

	@Test
    public void testConditonal() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
        System.out.println("\nioc容器已创建完成\n");

        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        String property = environment.getProperty("os.name");
        System.out.println("当前系统为: " + property);

        String[] beanNamesForType = applicationContext.getBeanNamesForType(Person.class);
        for (String beanName:beanNamesForType) {
            System.out.println("注入容器的person实例的名称为:" + beanName);
        }
    }

1.4 测试

运行testConditonal()可以得到下图。
由于我的系统是ubuntu16.04,因此可以看到,只有linus的person实例成功注入了容器中。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值