Spring 容器常見的裝配方式

通過各種裝配方式,幫助自己瞭解Spring容器在裝載的時候到底幹了什麼,以及容器在裝載的時候需要哪些東西?帶着問題熟悉一下。

Spring加載資源並進行裝配的過程,以XML的形式加載爲例
  1. 定義好Spring的配置文件
  2. 通過Resource對Spring的配置文件進行抽象,抽象成Resource對象
  3. 定義Bean的工廠
  4. 定義XMLBeanDefinitionReader對象,並將工廠作爲參數傳遞進去供後續回調使用
  5. 通過XMLBeanDefinitionReader讀取抽象出來的Resource對象
  6. 裝配完成,可以通過工廠獲取Bean

Resource,Spring對其內部使用到的資源全部抽象成Resource,通過Resource來封裝底層資源。
XMLBeanDefinitionReader是用來解析xml配置文件,最後裝配到Bean工廠。具體如何解析這邊不做詳細說明。

常見的裝配過程(不關注細節只關注過程)

bean.xml在這裏插入圖片描述
1、DefaultListableBeanFactory
  • Resource抽象Xml
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
//reader.loadBeanDefinitions(new ClassPathResource("bean.xml"));
reader.loadBeanDefinitions(new FileSystemResource("E:\\javaDev\\workspace\\tools\\src\\main\\resources\\bean.xml"));
factory.getBean("ccc");

解析:定義了一個DefaultListableBeanFactory工廠,並作爲參數傳入XMLBeanDefinitionReader,通過XMLBeanDefinitionReader讀取ClassPathResource或者FileSystemResource抽象出來的資源,從而完成裝載

  • AnnotatedBeanDefinitionReader註冊Bean
DefaultListableBeanFactory factory3 = new DefaultListableBeanFactory();
AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(factory3);
//註冊指定對象
annotatedBeanDefinitionReader.register(AAA.class,BBB.class);
System.out.println(factory3.getBean("BBB"));

解析:註冊指定對象,即使AAA.class沒有Spring註解,也能註冊到工廠

  • ClassPathBeanDefinitionScanner掃描包的方式註冊bean
DefaultListableBeanFactory factory3 = new DefaultListableBeanFactory();
ClassPathBeanDefinitionScanner classPathBeanDefinitionScanner = new ClassPathBeanDefinitionScanner(factory3);
//掃描包註冊
classPathBeanDefinitionScanner.scan("com.tools.springDemo");
System.out.println(factory3.getBean("AAA"));

解析:ClassPathBeanDefinitionScanner掃描包下面帶註解的Bean,如果AAA沒有@Component或者其他Spring自動裝載的註解,則無法註冊到BeanFactory;即使AAA對象在其他@Configuration配置類中,通過@Bean聲明,也不會註冊到BeanFactory;

2、XMLBeanFactory
繼承自DefaultListableBeanFactory,在Spring3.1以後XmlBeanFactory類被廢除了
	ClassPathResource classPathResource = new ClassPathResource("bean.xml");
	XmlBeanFactory factory2 = new XmlBeanFactory(classPathResource);
	factory2.getBean("ccc");
	System.out.println("\n"+factory2.getBean("ccc"));

解析:資源抽象爲ClassPathResource,加載到XmlBeanFactory容器中,此處並沒有見到XMLBeanDefinitionReader或其他的BeanDefinitionReader;那是因爲XMLBeanFactory默認使用XMLBeanDefinitionReader讀取Resource。如下圖

在這裏插入圖片描述

3、應用上下文裝載
  • AnnotationConfigApplicationContext ,javaConfig方式
	AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
	ac.register(AppConfig.class);
	ac.refresh();
	AAA aaa = (AAA)ac.getBean("AAA");
	System.out.println("\n[AAA] 獲取 AAA 對象:"+ac.getBean("AAA"));
  • ClassPathXmlApplicationContext ,xml方式
	ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
	applicationContext.getBean("ccc");
	System.out.println(applicationContext.getBean("ccc"));
注意:ApplicationContext爲什麼也能實現容器的功能?在這裏插入圖片描述
  • 他們都繼承自AbstractApplicationContext抽象類,而AbstractApplicationContext實現了ConfigurableApplicationContext接口,ConfigurableApplicationContext接口中有一個待實現的獲取容器的方法,如下
ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
  • 說白了,ApplicationContext內部持有一個DefaultListableBeanFactory來實現容器功能的。具體ApplicationContext作爲一個高級容器能幹什麼不闡述。

以上皆爲個人學習,如有問題請及時指出,謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章