文章目錄
- Spring 架構學習(三)---- IOC建立對象的方式
- 1、IOC 什麼時候建立對象?
- BeanFactory(不推薦使用)
- ApplicationContext
- 兩者差別
- 優缺點,各有利弊
- 2、IOC 如何建立對象?
- (1)根據參數下标進行指派(推薦)
- (2)根據參數類型進行指派(不推薦)
- (3)根據參數名進行指派(推薦)
- 3、IOC容器存儲一個bean,取出多個對象是否相同?
Spring 架構學習(三)---- IOC建立對象的方式
寫完了第一個Spring的程式,相信已經對spring已經有所了解了,那麼我們這節來了解一下,IOC是如何建立對象,什麼時候建立對象的。
1、IOC 什麼時候建立對象?
Spring 提供了兩種 IoC 容器,分别為 BeanFactory 和 ApplicationContext
我們先對兩種進行介紹一下
BeanFactory(不推薦使用)
BeanFactory 是基礎類型的 IoC 容器,簡單來說,BeanFactory 就是一個管理 Bean的工廠,它主要負責初始化各種 Bean,并調用它們的生命周期方法。
BeanFactory 接口有多個實作類,最常見的是 XmlBeanFactory類,它是根據 XML 配置檔案中的定義裝配 Bean 的。
建立 BeanFactory 執行個體時,需要提供 Spring 所管理容器的詳細配置資訊,這些資訊通常采用 XML 檔案形式管理。其加載配置資訊的代碼具體如下所示
BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource("D://applicationContext.xml"));
ApplicationContext
ApplicationContext 是 BeanFactory 的子接口,也被稱為應用上下文,它不僅提供了 BeanFactory 的所有功能,還添加了對 i18n(國際化)、資源通路、事件傳播等方面的良好支援。
ApplicationContext 接口有兩個常用的實作類,具體如下。
1)ClassPathXmlApplicationContext(重點認識)
該類從類路徑 ClassPath 中尋找指定的 XML 配置檔案,找到并裝載完成 ApplicationContext 的執行個體化工作,具體如下所示。
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(String configLocation);
2)FileSystemXmlApplicationContext(知道就行)
該類從指定的檔案系統路徑中尋找指定的 XML 配置檔案,找到并裝載完成 ApplicationContext 的執行個體化工作,具體如下所示。
ApplicationContext applicationContext = new FileSystemXmlApplicationContext(String configLocation);
在使用 Spring 架構時,可以通過執行個體化其中任何一個類建立 Spring 的 ApplicationContext 容器。
兩者差別
BeanFactory
BeanFactory在啟動的時候不會去執行個體化Bean,中有從容器中拿Bean的時候才會去執行個體化;
ApplicationContext
ApplicationContext在啟動的時候就把所有的Bean全部執行個體化了。
是以我們可以得知,對象在什麼時候建立,我們使用的是ApplicationContext,是以在Spring啟動的時候就已經把所有的Bean對象給建立好了。
優缺點,各有利弊
- 延遲執行個體化的優點:(BeanFactory)
先快後慢
應用啟動的時候占用資源很少;對資源要求較高的應用,比較有優勢;
- 不延遲執行個體化的優點: (ApplicationContext)
先慢後快
1. 所有的Bean在啟動的時候都加載,在後續的操作中系統運作的速度快;
2. 在啟動的時候所有的Bean都加載了,我們就能在系統啟動的時候,盡早的發現系統中的配置問題
2、IOC 如何建立對象?
(1)我們給實體類中加了一個無參構造方法、還有帶一個參數的構造方法。
package com.kuang.pojo;
public class Hello {
private String str;
public Hello() {
System.out.println("這是一個無參構造!");
}
public Hello(String str) {
this.str = str;
System.out.println("這是一個帶有一個參數的構造器!");
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
@Override
public String toString() {
return "Hello{" +
"str='" + str + '\'' +
'}';
}
}
(2)配置xml中的bean
<?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="hello" class="com.kuang.pojo.Hello">
<property name="str" value="Hello Spring!"/>
</bean>
</beans>
(3)編寫業務層代碼
package com.kuang.service;
import com.kuang.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloService {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
Hello hello = context.getBean("hello", Hello.class);
System.out.println(hello);
}
}
運作之後,預設調用的是無參的構造方法

我們可以得到一個結論:
如果不做專門的配置,那麼bean是通過無參構造來進行建立對象的
如果想要對實體類進行有參構造的建立怎麼實作呢?
IOC建立有參構造器對象的三種方式
這三種方式同樣,推薦大家一定要上spring的官方進行檢視,說的非常清楚了。
(1)根據參數下标進行指派(推薦)
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg index="0" value="7500000"/>
<constructor-arg index="1" value="42"/>
</bean>
- index 代表構造參數的下标,從0開始
- value 代表設定的值
在文檔中說明,通過index(從0開始),對對應位置的構造參數進行設定value,即可通過有參構造器建構對象
(1)寫一個User類,中有四個構造函數,有參,一個構造參數…,
package com.kuang.pojo;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
@Getter
@Setter
@ToString
public class User {
private int id;
private String userName;
private String password;
public User() {
System.out.println("無參構造進行建立對象!");
}
public User(int id) {
this.id = id;
System.out.println("一個參數構造的進行建立對象");
}
public User(int id, String userName) {
this.id = id;
this.userName = userName;
System.out.println("兩個參數構造進行建立對象");
}
public User(int id, String userName, String password) {
this.id = id;
this.userName = userName;
this.password = password;
System.out.println("三個參數構造進行建立對象");
}
}
(2)xml檔案通過下标的方式配置bean,隻設定了一個參數
<?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="user" class="com.kuang.pojo.User">
<constructor-arg index="0" value="1"/>
</bean>
</beans>
(3)然後通過ApplicationContext啟動Spring容器
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
User user = context.getBean("user",User.class);
}
(4)運作結果
(2)根據參數類型進行指派(不推薦)
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg type="int" value="7500000"/>
<constructor-arg type="java.lang.String" value="42"/>
</bean>
- type 構造參數的類型,如果是普通類型直接寫int、double,如果是引用類型寫全限定名
- value 設定的參數值
在文檔中說明,通過type(引用類型要寫全限定名),對對應類型的構造參數進行設定value,即可通過有參構造器建構對象
有一個問題,如果多個構造參數都是同一個類型呢?
答:會根據标簽的順序對同一類型的參數進行從前到後指派。
(1)前面的User類不變
(2)通過類型配置bean建立對象
<?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="user" class="com.kuang.pojo.User">
<constructor-arg type="int" value="1"/>
<constructor-arg type="java.lang.String" value="userName"/>
<constructor-arg type="java.lang.String" value="password"/>
</bean>
</beans>
(3)啟動Spring,如上
(4)檢視運作結果
(3)根據參數名進行指派(推薦)
<beans>
<bean id="thingOne" class="x.y.ThingOne">
<constructor-arg ref="thingTwo"/>
<constructor-arg ref="thingThree"/>
</bean>
<bean id="thingTwo" class="x.y.ThingTwo"/>
<bean id="thingThree" class="x.y.ThingThree"/>
</beans>
- name 構造參數的類型,如果是普通類型直接寫int、double,如果是引用類型寫全限定名
- value/ref 設定的參數值
這種方式看着非常直覺,非常容易了解,這種方式與設定類中的屬性是一樣的
其他都不變,xml配置檔案通過構造參數名字來建立對象
<?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="user" class="com.kuang.pojo.User">
<constructor-arg name="id" value="1"/>
<constructor-arg name="userName" value="root"/>
<constructor-arg name="password" value="123456"/>
</bean>
</beans>
檢視運作結果
3、IOC容器存儲一個bean,取出多個對象是否相同?
(1)編寫實體類User
package com.kuang.pojo;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class User {
private int id;
private String userName;
private String password;
}
(2)在xml配置檔案中裝配
<?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="user" class="com.kuang.pojo.User"/>
</beans>
(3)根據同一個bean取出多個對象
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
User user = context.getBean("user",User.class);
User user2 = context.getBean("user",User.class);
System.out.println(user==user2);
}
(4)運作結果