第二章、Spring IOC
控制反轉:Inversion of Controller(IoC)
依賴注入:Dependency injection(DI)
一、Spring IoC的概念及作用
(一)Spring IoC的概念及作用
ioc指的是控制反轉,指的就是以前我們獲取一個對象時採用的是自己創建一個的方式,這是一個主動的過程。
而控制反轉後,當我們需要對象時就跟工廠要,而工廠來幫我們創建或者查找對象,這是一個被動的過程。
這種被動接收對象的方式就是控制反轉。
IoC的作用是削減計算機程序的耦合(解除代碼中的依賴關係)
(二)程序的耦合
耦合度講的是模塊模塊之間,代碼代碼之間的關聯度,模塊間的耦合度是指模塊之間的依賴關係,包括控制關係、調用關係、數據傳遞關係。模塊間聯繫越多,其耦合性越強,同時表明其獨立性越差。
通過對系統的分析把他分解成一個一個子模塊,子模塊提供穩定的接口,達到降低系統耦合度的的目的,模塊模塊之間儘量使用模塊接口訪問,而不是隨意引用其他模塊的成員變量。
(三)解決程序耦合
1、通過反射機制,降低程序耦合
在最初使用jdbc 時,是通過反射來註冊驅動的,代碼如下:
Class.*forName*("com.mysql.jdbc.Driver");
此時,我們的類中不再依賴具體的驅動類,此時就算刪除 mysql 的驅動 jar 包,依然可以編譯。
2、工廠模式解耦合
/**
* 根據bean的名稱獲取Bean的對象
*/
public static Object getBean(String beanName) {
Object obj = null;
try {
String beanAllName = properties.getProperty(beanName);
obj = Class.forName(beanAllName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return obj;
}
3、單例模式解耦合
單例可以讓程序的對象在Java運行期間只有一個,節省了內存,有利於Java垃圾回收。然而單例有線程安全問題,但是我們平常一般不會講變量定義在屬性上,而是定義在方法內部,這樣就有力的避免了單例模式的線程安全問題。
public class BeanFactory {
private static Properties properties;
private static Map<String, Object> beans;
static {
try {
properties = new Properties();
properties.load(BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties"));
beans = new HashMap<>();
Set<String> keys = properties.stringPropertyNames();
for (String key : keys) {
String beanName = properties.getProperty(key);
beans.put(key,Class.forName(beanName).newInstance());
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} finally {
}
}
public static Object getBean(String beanName){
return beans.get(beanName);
}
}
二、Spring IoC
(一)Spring容器
在 Spring IOC 容器讀取 Bean 配置創建 Bean 實例之前, 必須對它進行實例化. 只有在容器實例化後, 纔可以從 IOC 容器裏獲取 Bean 實例並使用.
Spring 提供了兩種類型的 IOC 容器實現:
BeanFactory: IOC 容器的基本實現。
ApplicationContext: 提供了更多的高級特性. 是 BeanFactory 的子接口。
BeanFactory 是 Spring 框架的基礎設施,面向 Spring 本身,ApplicationContext 面向使用 Spring 框架的開發者,幾乎所有的應用場合都直接使用 ApplicationContext 而非底層的 BeanFactory
(二)ApplicationContext
ApplicationContext 的主要實現類:
1、ClassPathXmlApplicationContext:從類路徑下加載配置文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("conf/applicationContext.xml");
HelloService helloService = (HelloService) context.getBean("helloService");
2、FileSystemXmlApplicationContext: 從文件系統中加載配置文件
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("file:///E:/mytext/0525-spring2/src/main/resources/conf/applicationContext.xml");
HelloService helloService = (HelloService) context.getBean("helloService");
第一步生成工廠對象。加載完指定路徑下 bean 配置文件後,利用框架提供的 FileSystemXmlApplicationContext API 去生成工廠 bean。FileSystemXmlApplicationContext 負責生成和初始化所有的對象,比如,所有在 XML bean 配置文件中的 bean。
第二步利用第一步生成的上下文中的 getBean() 方法得到所需要的 bean。 這個方法通過配置文件中的 bean ID 來返回一個真正的對象。一旦得到這個對象,就可以利用這個對象來調用任何方法。
3、XmlWebApplicationContext:從Spring在web應用中載配置文件
XmlWebApplicationContext context = new XmlWebApplicationContext();
//設置配置文件的位置
context.setConfigLocation("classpath:applicationContext.xml");
//調用refresh()方法
context.refresh();
//從容器得到bean對象
HelloService helloService = (HelloService) context.getBean("helloService");