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的區別
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章