學習Spring5必知必會(3)~Spring的核心 IoC 和 DI
- 2022 年 2 月 26 日
- 筆記
- Spring的核心 IoC 和 DI
一、Spring的核心 IoC(基於XML)
1、IoC容器
(1)BeanFactory容器創建對象:
//使用BeanFactory
@Test
void testBeanFactory() throws Exception {
Resource resource = new ClassPathResource("com/shan/container/container.xml");
BeanFactory factory = new XmlBeanFactory(resource);
Person person = factory.getBean("person", Person.class);
}
(2)BeanFactory的子介面 ApplicationContext容器創建對象:
//使用ApplicationContext
@Test
void testApplicationContext() throws Exception {
//習慣將上下文對象命名為ctx
ApplicationContext ctx = new ClassPathXmlApplicationContext("com/shan/container/container.xml");
Person person = ctx.getBean("person", Person.class);
}
(3)bean創建時機(ApplicationContext 和 BeanFactory 創建對象的區別 ):
-
BeanFactory 在創建Spring容器的時候,並不會立馬創建容器中管理的Bean對象,需要等到獲取某一個 bean 的時候才會創建該 bean–延遲初始化。(懶載入)
-
ApplicationContext 在啟動 Spring 容器的時候就會創建所有的 bean(
在 Web 應用使用Application
)
□ 當然可以通過屬性設置懶載入:
對於某個bean對象,在該bean元素上通過 屬性lazy-init 進行設置; 對所有bean對象,在beans上通過 屬性default-lazy-init進行設置。
2、bean實例化方式(4種):
★ ① 構造器實例化(bean 中有 無參數構造器
),標準、常用
。
② 靜態工廠方法實例化:解決系統遺留問題。
③ 實例工廠方法實例化:解決系統遺留問題。
★ ④ 實現 FactoryBean 介面實例化:是第三種方式實例工廠的變種。 如集成 MyBatis 框架使用:org.mybatis.spring.SqlSessionFactoryBean
□ 方式2(工廠類中有一個創建bean對象的靜態方法):在xml的配置:
<bean id="" class="工廠類的全限定名" factory-method="工廠類中創建對象的靜態方法名"/>
□ 方式3(工廠類中有一個創建bean對象的方法):在xml的配置:
<bean id="factory3" class="工廠類的全限定名"/>
<bean id="create3" factory-bean="factory3" factory-method="工廠類中創建對象的方法名"/>
□ 方式4(實現 FactoryBean 介面實例化的方法):在xml的配置:(在方法3中,配置了兩個bean,咱的思路是:將其中一個bean “固定化”,
做法:將工廠實例化對象的方法規定為都叫 getObject 方法,因為咱定義的工廠類實現了FactoryBean介面(這是該介面的規範))
public class DogFactory implements FactoryBean<Dog>{
@Override
public Dog getObject() throws Exception {
Dog dog = new Dog();
return dog;
}
@Override
public Class<?> getObjectType() {
return Dog.class;
}
}
<!-- 實現 FactoryBean 介面實例化:實例工廠變種, 如集成 MyBatis 框架使用 -->
<bean id="dog" class="com.shan._04_factory_bean.DogFactory"/>
/* 使用spring的測試框架 */
@SpringJUnitConfig
public class App {
@Autowired
private Person person;
@Autowired
private BeanFactory factory;
@Autowired
private ApplicationContext ctx;
@Autowired
private Dog dog;
@Test
void testBeanFactory() throws Exception {
System.out.println(person);
System.out.println(dog);
}
}
3、bean作用域scope(常用單例)
-
在 Spring 容器中是指其創建的 Bean 對象相對於其他 Bean 對象的請求可見範圍,定於語法格式:
<bean id=”” class=”” scope=”作用域”/>
-
單例和多例: singleton: 單例(默認的作用域) prototype: 多例
-
在web應用中(request、session、application)
-
globalSession: 一般用於 Porlet 應用環境 , 分散式系統存在全局 session 概念(單點登錄)
-
websocket:將一個bean定義定義到WebSocket的生命周期
-
-
預設情況下是單例 singleton
4、bean初始化和銷毀
- 屬性init-method=”該類中初始化方法名” 和 屬性destroy-method=”該類中銷毀方法名”
- 沒有使用spring的測試框架的話,就不能正常關閉IoC容器,即銷毀bean對象了(可以手動關閉)
<bean id="cat" class="com.shan.lifecycle.Cat" init-method="init" destroy-method="close"/>
■ bean 的生命周期:bean 從出生到消亡的整個過程。
BeanFactory:延遲初始化特點
ApplicationContext:在啟動Spring容器的時候,就會去創建bean對象
5、bean的生命周期
①執行Bean 構造器 ②為Bean注入屬性 ③調用Bean元素的init-method 進行初始化 ④獲取Bean對象,調用Bean對象的某個方法 ⑤調用Bean元素的destroy-method 進行銷毀對象 ⑥銷毀Spring容器
二、Spring的 DI
-
DI:Dependency Injection (依賴注入):Spring 創建對象的過程轉給你,將對象依賴的屬性(常量、對象、集合)通過配置設置值給該對象
-
IoC: 將對象的創建權,反轉給了Spring容器
■ 注入:☺ 簡單理解就是給對象設置值
(通過對象的setter方法【屬性注入方法】、通過對象的構造器設置值【構造器注入方法】)
□ 設置值的類型:
- 常量類型(固定不變),簡單類型 value
- 對象類型(引用類型) ref
- 集合類型 各自集合對應的元素
- …
1、通過XML配置裝配
(1)XML自動裝配(不推薦)通過bean元素的屬性 autowire 自動裝配
✿(2)setter注入 [ 屬性注入(根據類型區分)]
■(常用
) 注入常量 value
<bean id="person" class="com.shan.di_setter.Person">
<property name="name" value="shan"/>
<property name="age" value="22"/>
<property name="salary" value="10000"/>
</bean>
■(常用
) 注入對象 ref
<bean id="cat" class="com.shan.di_setter2.Cat">
<property name="name" value="kity"/>
</bean>
<bean id="person" class="com.shan.di_setter2.Person">
<property name="name" value="shan"/>
<property name="age" value="22"/>
<property name="cat" ref="cat"/>
</bean>
■ 注入集合 、
<bean id="person" class="com.shan.di_setter3.Person">
<!-- set類型 -->
<property name="set">
<set>
<value>set1</value>
<value>set2</value>
<value>set3</value>
</set>
</property>
<!-- list類型 -->
<property name="list">
<list>
<value>list1</value>
<value>list2</value>
</list>
</property>
<!-- array類型 -->
<property name="array">
<array>
<value>array1</value>
</array>
</property>
<!-- map類型(字典類型) -->
<property name="map">
<map>
<entry key="key1" value="value1"/>
</map>
</property>
<!-- properties類型(特殊的map類型【key和value都是字元串】) -->
<property name="prop">
<value>
p1=v1
p2=v2
</value>
</property>
</bean>
● 屬性的設置值是在 init 方法執行之前完成。com.shan.di_construstor
(3)構造器注入(跟屬性注入差不多,常用的是屬性注入
,就是將property換成constructor-arg 元素)
<!-- 構造器注入:常量類型 -->
<bean id="person" class="com.shan.di_construstor.Person">
<constructor-arg name="name" value="shan"/>
<constructor-arg name="age" value="18"/>
<constructor-arg name="salary" value="10000"/>
</bean>
<!-- 構造器注入:對象類型 -->
<bean id="cat" class="com.shan.di_construstor.Cat"/>
<bean id="person2" class="com.shan.di_construstor.Person2">
<constructor-arg name="c" ref="cat"/>
</bean>
<!-- 構造器注入:集合類型 -->
✿(4)bean元素繼承 (本質是xml配置內容的拷貝)
- 通過abstract屬性進行抽取
- 通過parent屬性進行引入
(5) 配置資料庫連接池
<!-- 配置資料庫連接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/springdemo?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="admin"/>
<property name="initialSize" value="2"/>
</bean>
✿ 動態載入配置文件(db.properties—資料庫連接的配置資訊)
(6)property place holder
1)要是使用標籤Context,需要先引入Context的約束(在beans的基礎進行修改即可):
2) context:property-placeholder 屬性佔位符
<!-- 從classpath的根路徑 載入db.properties -->
<context:property-placeholder location="classpath:db.properties"/>
3)使用 ${} 動態引入屬性值
<!-- 配置資料庫連接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="initialSize" value="${jdbc.initialSize}"/>
</bean>