二.Spring的 核心技術
目錄
一,IOC 容器
IOC 也成爲 DI(dependency injection) , 它是對象定義其依賴關係的過程. 一般對象通過構造器參數、工廠方法參數或者構造(工廠方法返回實例)之後 set 相應的屬性完成依賴配置. 容器在創建Bean的時候注入這些依賴,這個過程從根本上來說是反轉,因此叫做 IOC , 它通過直接構建類來控制其初始化或依賴類的位置。這種機制類似服務定位器設計模式。
Spring Framework 的 IOC 容器的基礎包是 org.springframework.beans 與 org.springframe.context. 其中接口 BeanFactory 提供框架配置和基本功能,其子接口 ApplicationContext 增加了更多的企業級功能,如國際化資源處理、事件發佈以及應用層特定的上下文(如用於web應用的 WebApplicationContext).ApplicationContext 是 BeanFactory 完整的超集.
我理解的 IOC : 即控制反轉,依賴注入, ioc是Spring的核心組件,它通過配置文件將需要的創建的對象以池的方式管理。 動態注入, 讓一個對象的創建不用new了,可以自動的生產,這其實就是利用 java 裏的反射,反射其實就是在運行時動態的去創建,調用對象,Spring就是在運行時,跟 xml Spring 的配置文件來動態的創建對象,和調用對象裏的方法的。
- 多實例,僅當 bean 被使用的時候才創建
- 單實例,創建 IOC 容器的時候實例, bean 就被創建了 (面試經常被問到);
單實例,多實例源碼分析實例:https://blog.csdn.net/Crazy_Cw/article/details/90980030 @Scope 註解
2.1.1,代碼示例:在沒有 Spring 的管理下
public class Person {
private String name;
private Integer age;
public Person(){
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
public Integer getAge() {
return age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public void setAge(Integer age) {
this.age = age;
}
}
//如果沒有用到Spring 我們是怎麼做的呢?
public class Test {
//在一般java的獲得實例對象時
Person per =new Person();
}
2.1.2,示例代碼:在 Spring 的管理下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="person" class="com.enjoy.cap1.Person">
<property name="name" value="james"></property>
<property name="age" value="19"></property>
</bean>
</beans>
public class Test{
public static void main(String args[]){
//把beans.xml的類加載到容器
ApplicationContext app = new ClassPathXmlApplicationContext("beans.xml");
//從容器中獲取bean
Person person = (Person) app.getBean("person");
System.out.println(person);
}
}
二,容器概述
ApplicationContext 接口相當於負責 bean 的初始化、配置和組裝的IoC容器.
Spring爲ApplicationContext 提供了一些開箱即用的實現, 獨立的應用可以使用 ClassPathXmlApplicationContext 或者 FileSystemXmlApplicationContext,web 應用在 web.xml 配置監聽,提供xml位置和org.springframework.web.context.ContextLoaderListener 即可初始化 WebApplicationContextIoC 容器.
三 ,配置元數據
配置元數據配置了應用中實例的實例化、配置以及組裝的規則,SpringIoC容器通過此配置進行管理Bean. 配置元數據有以下幾種方式:
基於XML配置: 清晰明瞭,簡單易用基於Java代
碼配置:無xml,通過 @Configuration 來聲明配置、對象實例化與依賴關係
示例代碼1.3:@Configuration 來聲明配置、對象實例化與依賴關係
//配置類====配置文件
@Configuration
public class PersonConfig {
//給容器中註冊一個bean, 類型爲返回值的類型,
@Bean("person")
public Person person01(){
return new Person("james",20);
}
}
基於Java註解配置:少量的 XML(<context:annotation-config/>),通過註解聲明實例化類與依賴關係
後續的分析基於XML配置, 與Java代碼和註解大體上的機制是一樣
四,實例化容器
實例化容器非常簡單,只需要提供本地配置路徑或者根據ApplicationContext的構造器提供相應的資源(Spring的另一個重要抽象)即可.
2.4.1示例代碼
//這是通過類路徑找到 自定義的 springxml
ApplicationContext app = new ClassPathXmlApplicationContext("beans.xml");
此處先給出類圖, 稍後再做具體分析.
五,Bean 概述
Spring IOC 容器管理了多個根據配置元數據創建的bean. 在容器內部,這些 Bean 可以描述爲 BeanDefinition
對象,它主要包含這些元數據:
- 全類名:通常爲 Bean 的實際實現類
- Bean 的行爲配置元素,這種狀態描述了 Bean 在容器中的行爲,如作用域、生命週期回調等等.
- 當前 Bean 依賴 Bean 的引用: 依賴項
- 新創建對象中的其他配置設置,如池對象 Bean 的池大小限制等.
容器除了通過配置元數據管理bean之外, 還可以通過 ApplicationContext
的方法 getBeanFactory()
獲取, BeanFactory
的實現 DefaultListableBeanFactory
來註冊自己的bean, 但不建議使用.
2.5.1,Bean 的創建
//第一種通過xml 方式來註冊bean
<bean id="person" class="com.enjoy.cap1.Person"/>
//第二種方式 使用註解 @bean
@Bean("person")
public Person person01(){
return new Person("james",20);
}
2.5.2,Bean 的實例化
可以將bean的定義想象爲創建對象的菜譜,容器在請求時查看對應bean的配方(配置元數據),並使用該配方創建實際對象.
使用XML配置元數據的時候需要指定bean的class屬性,class屬性強制作爲BeanDefinition的getBeanClassName()值,但這個屬性不一定是運行時的最終類名(靜態工廠方法或者類繼承).
使用Class屬性有種方式:
- 通常,當容器本身通過反射調用其構造函數直接創建bean的時候需要制定Class,這與new ...()操作類似
- 指定包含靜態工廠方法的實際類,該方法用於創建對象.
<bean id="person" class="com.enjoy.cap1.Person" />
2.5.3, Bean 的生命週期
- 創建---初始化---銷燬的過程
- bean 的生命週期是由容器管理的
- 我們可以自定義bean 初始化, 銷燬的方法
- 容器在bean 進行到當前生命週期的時候,來調用自定義的初始化和銷燬方法
詳細的 Bean 的生命週期 Spring 源碼 示例 請看 -----》Spring源碼深度解析,初始Spring源碼---Bean的生命週期(五)(附代碼示例:)https://blog.csdn.net/Crazy_Cw/article/details/92437266
六,項目Demo地址,正在持續更新~~~~~~~~~~
Spring源碼深度解析,(附代碼示例 碼雲地址: https://gitee.com/Crazycw/SpringCode.git)
參考資料: https://docs.spring.io/spring/docs/4.3.18.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/
請看下篇: Spring源碼深度解析,初始Spring源碼(三)(附代碼示例:)