什么是Spring的IOC
1尿背、IOC是Inversion of Control簡(jiǎn)寫默赂,中文稱之為控制反轉(zhuǎn)
2捻激、作用時(shí)將對(duì)象的創(chuàng)建權(quán)交由Spring框架去管理钧排,在沒用框架之前敦腔,創(chuàng)建對(duì)象是我們采用new xxx()來創(chuàng)建該對(duì)象,在Spring中對(duì)象的創(chuàng)建是交給IOC容器的恨溜,不需要我們自己去創(chuàng)建
3符衔、作用是降低了代碼的耦合度
SpringIOC創(chuàng)建對(duì)象
目標(biāo):
通過IOC創(chuàng)建對(duì)象,調(diào)用對(duì)象的中方法
1糟袁、整個(gè)項(xiàng)目目錄
2判族、IDEA創(chuàng)建普通的maven項(xiàng)目,也可創(chuàng)建普通項(xiàng)目java項(xiàng)目導(dǎo)入架包
3项戴、打開項(xiàng)目找到pom.xml文件配置如下主要是 <dependencies> </dependencies>里面的包
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>springNewBean</groupId>
<artifactId>work.chenc</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- junit測(cè)試包 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- spring-context 包含Spring必須的架包-->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
</dependencies>
</project>
spring-context 包含Spring必須的架包
4形帮、新建一個(gè)類,并給類一個(gè)方法
package work.chenc.entity;
public class UserEntity {
public UserEntity() {
System.out.println("UserEntity無參構(gòu)造----------------");
}
public void doSomething() {
System.out.println("UserEntity-doSomething........");
}
}
5周叮、新建一個(gè)xml文件辩撑,位置可以自選,我選擇的是在resources目錄下
<?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">
<!--
id: getBean(id) 通過id獲取實(shí)例化的對(duì)象
class: 需要?jiǎng)?chuàng)建對(duì)象的全路徑-根據(jù)類的全路徑獲取類的class(字節(jié)碼)
-->
<bean id="user" class="work.chenc.entity.UserEntity"></bean>
</beans>
6则吟、Junit測(cè)試-調(diào)用UserEntity中的doSomething方法
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import work.chenc.entity.UserEntity;
public class NewBeanTest {
@Test
public void testIocNewBean() {
// 1槐臀、獲取ApplicationContent對(duì)象解析xml文件并創(chuàng)建對(duì)象 - spring內(nèi)部處理
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:bean.xml");
// 2、獲取創(chuàng)建的對(duì)象
UserEntity userEntity = context.getBean("user", UserEntity.class);
userEntity.doSomething();
}
}
補(bǔ)充說明:通過執(zhí)行結(jié)果可知氓仲、這里創(chuàng)建對(duì)象調(diào)用了類的無參構(gòu)造方法水慨,而我們New UserEntity() 默認(rèn)也只調(diào)用無參構(gòu)造
IOC底層原理
一、IOC之前創(chuàng)建對(duì)象的方法
通過圖解可以看出原始方法對(duì)象之間的耦合性非常高敬扛,采用工廠雖然能降低UserDao和UserService之間的耦合性但是userFactory和UserService之間的耦合性還是非常高晰洒,為了解決這一情況,Spring為我們提供了IOC控制反轉(zhuǎn)啥箭,他能進(jìn)一步降低類與類之間的耦合性
IOC實(shí)現(xiàn)控制反轉(zhuǎn)
實(shí)現(xiàn)IOC主要用到的技術(shù):XML解析谍珊、工廠模式、反射
通過IOC創(chuàng)建對(duì)象的重點(diǎn)在與xml文件急侥,如果類的路徑發(fā)成改變砌滞,我們只需要修改對(duì)應(yīng)的類的class屬性即可侮邀,這樣就大大的降低了代碼之間的耦合性
IOC接口說明
1、IOC思想是基于IOC容器贝润,IOC容器的底層實(shí)現(xiàn)就是對(duì)象工廠
2绊茧、Spring提供了兩種實(shí)現(xiàn)IOC的方式
a.BeanFactory:IOC容器的基本實(shí)現(xiàn),是Spring內(nèi)部使用的接口打掘,不提供開發(fā)人員使用
b.ApplicationContext: BeanFactory接口的子類华畏,提供了更強(qiáng)大的功能,一般供開發(fā)人員使用
區(qū)別:
BeanFactory在加載配置文件時(shí)尊蚁,不會(huì)創(chuàng)建對(duì)象亡笑,再獲取對(duì)象(使用)對(duì)象的時(shí)候才會(huì)創(chuàng)建
ApplicationContext在加載配置文件時(shí)就會(huì)創(chuàng)建對(duì)象(項(xiàng)目啟動(dòng)加載配置文件就會(huì)創(chuàng)建對(duì)象)
3、ApplicationContext接口的實(shí)現(xiàn)類
FileSystemXmlApplicationContext:這里路勁必須系統(tǒng)絕對(duì)路徑
ClassPathXmlApplicationContext:這里src下的路徑
// 1横朋、根據(jù)ApplicationContent 上下文對(duì)象解析并加載配置文件bean.xm 在src目錄下
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
ApplicationContext context = new FileSystemXmlApplicationContext("系統(tǒng)下的絕對(duì)路徑");
補(bǔ)充:
藍(lán)色的實(shí)線===》類繼承類
綠色的實(shí)線===》 接口繼承接口
綠色的虛線===》 類實(shí)現(xiàn)接口
由上圖可以確定 ApplicationContent的確BeanFactory的子類仑乌,F(xiàn)ileSystemXmlApplicationContext及ClassPathXmlApplicationContext都是ApplicationContext的實(shí)現(xiàn)類
簡(jiǎn)單實(shí)現(xiàn)通過配置文件及反射創(chuàng)建對(duì)象并調(diào)用對(duì)象方法
這里需要一個(gè)dom4j
架包,我這里直接使用的Maven創(chuàng)建的普通項(xiàng)目叶撒,測(cè)試用的junit架包绝骚,這是我的pom.xml引入的架包
ps:dom4j在解析xml需要用到
<dependencies>
<!-- 測(cè)試包 -->
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- 引入dom4j -->
<!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
</dependencies>
1、創(chuàng)建一個(gè)UserDao類祠够,代碼如下
public class UserDao {
public void find() {
System.out.println("------------執(zhí)行了UserDao.find()方法------------");
}
}
2、創(chuàng)建一個(gè)bean.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="user" class="entity.UserDao"></bean>
</beans>
3粪牲、核心代碼
// 1古瓤、獲取文件 - 絕對(duì)路徑
File file = new File("/Users/chenlibrary/Documents/project/chenlibrary/SpringIOC_demo/src/main/resources/bean.xml");
// 相對(duì)路徑
// File file = new File("src/main/resources/bean.xml");
// 2、獲取文件流
FileInputStream inputStream = new FileInputStream(file);
// 3. 創(chuàng)建SAXReader對(duì)象
SAXReader reader = new SAXReader();
// 4腺阳、獲取文件Document對(duì)象
Document doc = reader.read(inputStream);
// 獲取文件節(jié)點(diǎn)
Element root = doc.getRootElement();
// 獲取文件中所有bean元素
List<Element> list = root.elements("bean");
// 迭代
if (list != null && list.size() > 0) {
for (Element bean : list) {
// 反射操作
Class clazz = Class.forName(bean.attributeValue("class"));
//生成對(duì)象
UserDao userDao = (UserDao) clazz.newInstance();
userDao.find();
}
}
File file = new File("XXXX")落君,這里可以根據(jù)xml的絕對(duì)路徑或相對(duì)路徑找到xml文件
絕對(duì)路徑
window下及從盤符開始到xml文件的目錄,我這里是mac下的絕對(duì)路勁
相對(duì)路徑
是從當(dāng)前項(xiàng)目的位置開始找的,下圖是我的xml文件地址
這里只是簡(jiǎn)單的實(shí)現(xiàn)了IOC的中的通過解析xml配置亭引,再通過反射獲取配置文件中類的字節(jié)碼文件在創(chuàng)建對(duì)象绎速,至于工廠模式這里暫無涉及,待后續(xù)繼續(xù)學(xué)習(xí)焙蚓。