Spring学习笔记(二):bean的注册加载

Spring学习笔记(二):bean的注册加载

@Conditional条件注册bean

  • 场景:向IoC容器注册bean时,当操作系统为Windows时,注册Sansa实例,当操作系统为Linux时,注册Rob实例。
  • 解决方案:使用@Conditional注解进行定制化条件选择注册bean。
  1. 配置类
@Configuration
public class MainConfig {
    @Bean("person")
    pubic Person person() {
        System.out.println("add John to IoC Container,");
        return new Person("John", 20);
    }
    
    @Condition({WinCondition.calss})
    @Bean("Sansa")
    public Person Sansa() {
        System.out.println("add Sansa to IoC Container");
        return new Person("Sansa", 18)
    }
    
    @Condition({LinCondition.calss})
    @Bean("Rob")
    public Person Rob() {
        System.out.println("add Rob to IoC Container");
        return new Person("Rob", 21);
        
    }
}
  1. 条件类WinCondition.java,需实现Spring提供的Condition接口
public class WinCondition implements Condition {
    
    /**
    ConditionContext:判断条件能使用的上下文环境
    AnnotatedTypeMetadata:注释信息
    **/
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMedata metadata) {
        //1.获取IoC容器使用的beanFactory
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //2.获取类加载器
        ClassLoader classloader = context.getClassLoader();
        //3.获取当前环境信息
        Enviroment enviorment = context.getEnviroment();
        //4.获取bean定义的注册类
        BeanDefinitionRegistry registry = context.getRegistry();
        
        String property = enviroment.getProperty("os.name");
        if (property.contians("Windows")) {
            return true;
        }
        return false;
    }
    
} 
  1. 新建Linux条件类,用来处理操作系统为Linux的bean注册
public class LinCondition implements Condition {
    
    /**
    ConditionContext:判断条件能使用的上下文环境
    AnnotatedTypeMetadata:注释信息
    **/
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMedata metadata) {
        //1.获取IoC容器使用的beanFactory
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //2.获取类加载器
        ClassLoader classloader = context.getClassLoader();
        //3.获取当前环境信息
        Enviroment enviorment = context.getEnviroment();
        //4.获取bean定义的注册类
        BeanDefinitionRegistry registry = context.getRegistry();
        
        String property = enviroment.getProperty("os.name");
        if (property.contians("linux")) {
            return true;
        }
        return false;
    }
    
} 
  1. 测试类
//打印IoC容器里的所有person实例名
@Test
public void test() {
    //声明IoC容器时获取环境
    AnnotationConfigApplicationContext anno = new AnnotationConfigApplicationContext(MainConfig.class);
    ConfigurableEnviroment enviroment = anno.getEnviroment();
    String property = enviroment.getProperty("os.name");
    System.out.println(property);//打印当前环境的操作系统
    //根据类型获取容器中的所有bean
    String[] beanNamesForType = anno.getBeanNamesForType(Person.class);
    for(String name : beanNamesForType) {
        System.out.println("name");
    }
    //打印所有bean,把所有对象和ID放入Map中
    Map<String, Person> personBean = anno.getBeansOfType(Person.class);
    System.out.println("personBean");
}
  • 当引入@Conditional注解时,容器可以有选择性地注册bean

@Import注册bean

使用@Import注解来注册已有类(通常用来加载依赖包中的类)

@Import(Targaryen.class, Lannister.class, Baratheon.class)
public class MainConfig {
    @Bean("Stark")
    public Stark stark() {
        return new Stark("Stark", "wolf");
    }
}

实现FactoryBean接口来加载bean

  1. 自定义工厂bean
/*创建一个自定义FactoryBean
* a.默认获取到的是工厂bean调用getObject创建的对象
* b.要获取工厂bean本身,需要在获取bean时前面加“&”
**/
public class StarkFactoryBean implements FactoryBean<Family> {
    //容器调用getObject()方法返回对象,把对象放入容器中
    //返回一个Family对象,添加到容器中
    @Override
    public Family getObject() throws Execption {
        return new Family();
    }
    
    //返回对象类型
    @Override
    public Class<?> getObjectType() {
        return Family.class;
    }
    
    //是否为单例,单例:在容器中只保存一份该bean
    @Override
    public boolean isSingleton() {
        return true;
    }
    
}
  1. 配置类
@Configuration
@Import(Targaryen.class, Lannister.class, Baratheon.class)
public class MainConfig {
    @Bean
    public StarkFactoryBean starkFactoryBean() {
        return new StarkFactoryBean();
    }
}
  1. 获取bean
    //获取FactoryBean调用getObject方法返回的bean
    Object family = app.getBean("starkFactoryBean");
    
    //获取StarkFactoryBean本身
    object starkFactoryBean = app.getBean("&starkFactoryBean");

FactoryBean是一个接口,当在IOC容器中的Bean实现了FactoryBean后,通过getBean(String BeanName)获取到的Bean对象并不是FactoryBean的实现类对象,而是这个实现类中的getObject()方法返回的对象。要想获取FactoryBean的实现类StarkFactoryBean,就要getBean(&BeanName),在BeanName之前加上&。

总结:bean的几种注册加载方式

  1. 包扫描+组件标注注解(@Controller、@Service、@Repository、@Component):一般针对自行定义的类
  2. @Bean:导入第三方类或包的组件
  3. @Import:快速导入一个组件到容器
  • a.@Import,id默认是全类名
  • b. ImportSelector接口,返回需要导入的组件的全类名数组
  • c.ImportBeanDefinitionRegistrar
  1. 使用Spring提供的FactoryBean(工厂Bean)
    注:FactoryBean与BeanFactory的区别
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章