Spring注解--@Conditional、@Import详解

@Conditional

按照一定条件进行判断,满足条件给容器注册Bean
参数:Condition数组

写在方法上:
示例:根据操作系统注册Bean

	@Conditional(WindowsCondition.class)//判断条件
    @Bean("bill")//windows系统注册该Bean
    public Person person01(){
        return new Person("Bill Gates", 62);
    }

    @Conditional(LinuxCondition.class)
    @Bean("linus")//linux系统注册该Bean
    public Person person02(){
        return new Person("Linus", 48);
    }

定义两个条件:

package pers.zhang.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;

/**
 * @author zhang
 * @date 2019/12/1 - 16:03
 */
//判断是否为linux系统
public class LinuxCondition implements Condition {

    /*
        参数ConditionContext:判断条件所使用上下文环境
        参数AnnotatedTypeMetadata:标注了Conditional的注释信息
     */
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        //可以获取Bean的创建工厂
        ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
        //可以获取类加载器
        ClassLoader classLoader = conditionContext.getClassLoader();
        //可以获取Bean定义的注册类
        BeanDefinitionRegistry registry = conditionContext.getRegistry();
        //获取环境信息
        Environment environment = conditionContext.getEnvironment();
        //获取操作系统
        String system = environment.getProperty("os.name");
        if(system.contains("linux")){
            return true;
        }
        return false;
    }
}
package pers.zhang.condition;

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;

/**
 * @author zhang
 * @date 2019/12/1 - 16:03
 */
//判断是否为windos系统
public class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        //也可以判断容器中是否包含某个Bean
        //BeanDefinitionRegistry registry = conditionContext.getRegistry();
        //registry.containsBeanDefinition("xxx")
        //获取环境信息
        Environment environment = conditionContext.getEnvironment();
        //获取操作系统
        String system = environment.getProperty("os.name");
        if(system.contains("Windows")){
            return true;
        }
        return false;
    }

}

测试:

	@Test
    public void printBeans(){
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig.class);
        String[] definitionNames = ac.getBeanDefinitionNames();
        for(String name : definitionNames){
            System.out.println(name);
        }
    }

Spring注解--@Conditional、@Import详解_第1张图片

写在类上:
满足当前条件,这个类中配置的所有Bean注册才能生效



@Import

@Import 注解可以普通类导入到 IoC容器中。

想要让一个普通类接受 Spring 容器管理,有以下方法

  • 使用 @Bean 注解
  • 使用 @Controller @Service @Repository @Component 注解标注该类,然后再使用 @ComponentScan 扫描包
  • @Import 方法,即现在这种方式

第一种方式:

@Import(要导入到容器中的组件)

//参数为数组,id默认为全类名

示例:

package pers.zhang.bean;

public class Color {
}
package pers.zhang.bean;

public class Red {
}
package pers.zhang.config;

import org.springframework.context.annotation.*;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import pers.zhang.bean.Color;
import pers.zhang.bean.Person;
import pers.zhang.bean.Red;
import pers.zhang.service.BookService;


@Configuration
@ComponentScan("pers.zhang")
@Import({Color.class, Red.class})//导入组件
public class MainConfig {

    //给容器中注册一个Bean,类型为返回值的类型,方法名作为id;也可以指定id:@Bean("id")
    @Bean
    @Scope("singleton")
    @Lazy
    public Person person(){
        return new Person("zhangsan", 18);
    }
}
@Test
    public void printBeans(){
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig.class);
        String[] definitionNames = ac.getBeanDefinitionNames();
        for(String name : definitionNames){
            System.out.println(name);
        }
    }

Spring注解--@Conditional、@Import详解_第2张图片

第二种方式:实现ImportSelector
返回需要导入的组件的全类名的数组

package pers.zhang.bean;

public class Yellow {
}
package pers.zhang.bean;

public class Blue {
}

实现ImportSelector

package pers.zhang.condition;

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

/**
 * @author zhang
 * @date 2019/12/1 - 15:22
 */
//自定义逻辑返回需要导入的组件
public class MyImportSelector implements ImportSelector {

    //返回值:就是要导入到容器中的组件全类名
    //AnnotationMetadata:当前标注@Import注解的类的所有注解信息
    //可以返回空数组,不可以返回null,会报空指针异常!
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{"pers.zhang.bean.Blue", "pers.zhang.bean.Yellow"};
    }
}

添加到Import参数中

@Import({Color.class, Red.class, MyImportSelector.class})

Spring注解--@Conditional、@Import详解_第3张图片

第三种方式:实现ImportBeanDefinitionRegistrar
手动注册方式,可以指定Bean的定义信息

package pers.zhang.bean;

public class Green {
}

实现ImportBeanDefinitionRegistrar:

package pers.zhang.condition;

import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import pers.zhang.bean.Green;

/**
 * @author zhang
 * @date 2019/12/1 - 15:36
 */
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    /*
        参数:AnnotationMetadata,当前类注解信息
        参数:BeanDefinitionRegistry,BeanDefinition注册类
            把所有需要添加到容器中的Bean;调用BeanDefinitionRegistry.registerBeanDefinition手动注册进来
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        boolean blue = beanDefinitionRegistry.containsBeanDefinition("pers.zhang.bean.Blue");
        boolean red = beanDefinitionRegistry.containsBeanDefinition("pers.zhang.bean.Red");
        if(blue && red){//如果包含蓝色和红色就注册绿色
            //指定Bean的定义信息(类型,Scope)
            RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Green.class);
            //可以指定Bean名
            beanDefinitionRegistry.registerBeanDefinition("green", rootBeanDefinition);
        }
    }
}

修改Import参数:

@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})

Spring注解--@Conditional、@Import详解_第4张图片

你可能感兴趣的:(Spring)