一. spring的啟動:
web.xml:
<!-- 加載spring容器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext-*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>
從配置文件中,便知道spring在web項目中由監聽器ContextLoaderListener加載對應的spring配置文件applicationContext-*.xml完成對spring的啟動。
二.bean的生成【有xml和組件掃描兩種方式】:
例如在spring+springmvc的項目中,往往controller層使用組件掃描,而service層則使用xml配置文件的方式,具體如下:
對於以下需求:
controller層(組件掃描):
service層(xml配置文件的方式):
以xml為例,分析service層對應bean的生成:
1.service為單例(默認就是單例,並且不適用懶加載):
在spring啟動時便將bean(userService)實例化。實例化過程:spring容器中BeanFactory(bean工廠)根據xml配置文件,獲得要實例化的bean的全類名,通過反射生成對應實例。
2.service是單例(但xml配制文件中設置懶加載模式(lazy-init=”true”))或者service為多例(此時懶加載不起作用):只有在getBean或者說使用bean時才實例化。
推薦博文:spring依賴注入的實現原理
三. spring ioc依賴注入的過程:
該過程與bean的生成密不可分,當一個bean(UserController對象)被創建時,該bean所擁有的依賴(userService)就要被注入(實例化),依賴注入過程同樣是調用BeanFactory,獲取所依賴的屬性(依賴注入的方式:構造方法,set方式,注解方式等, 獲取方法不盡相同),再查找xml配置文件,通過反射實例化對應的依賴,並將實例化后的依賴(userService)封裝(反射相關操作)進bean(UserController對象)中,至此,依賴注入完成。
這里補充一個特殊情況【引用自他人博客】:比如Service1引用了Service2,而Service2也引用了Service1。如果現在正在創建Service1,發現它依賴了Service2,在向Service1注入Service2的過程中肯定要先去創建Service2。這時候發現又要創建Service1,當然不能再創建一個Service1了,而是先將未初始化好的Service1引用先注入到Service2中,然后初始化Service2后再回過來注入到Service1中。
UserController