Spring到底是如何來實現IOC和DI的,那接下來就通過一些簡單的入門案例,來演示下具體實現過程。
目錄
前期準備
一、IOC入門案例
思路分析
代碼實現
二、DI入門案例
思路分析
代碼實現
總結
前期準備
使用IDEA創建Maven項目,首先需要配置好Maven,新建一個Maven項目。
一、IOC入門案例
思路分析
(1)Spring是使用容器來管理bean對象的,那么管什么?
- 主要管理項目中所使用到的類對象,比如(Service和Dao)
(2)如何將被管理的對象告知IOC容器?
-
使用配置文件
(3)被管理的對象交給IOC容器,要想從容器中獲取對象,就先得思考如何獲取到IOC容器?
-
Spring框架提供相應的接口
(4)IOC容器得到后,如何從容器中獲取bean?
-
調用Spring框架提供對應接口中的方法
(5)使用Spring導入哪些坐標?
-
用別人的東西,就需要在pom.xml添加對應的依賴
代碼實現
(1)創建Maven項目,在pom.xml 添加Spring的依賴jar包,
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.10.RELEASE</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency>
</dependencies>
(2)創建BookService,BookServiceImpl,BookDao和BookDaoImpl四個類,
目錄如下:
package com.water.dao;public interface BookDao {public void save();
}
package com.water.dao.impl;import com.water.dao.BookDao;public class BookDaoImpl implements BookDao {public void save() {System.out.println("book dao save ...");}
}
package com.water.server;public interface BookService {public void save();
}
package com.water.server.impl;import com.water.dao.BookDao;
import com.water.dao.impl.BookDaoImpl;
import com.water.server.BookService;public class BookServiceImpl implements BookService {private BookDao bookDao = new BookDaoImpl();public void save() {System.out.println("book service save ...");bookDao.save();}
}
(3)resources下添加spring配置文件applicationContext.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標簽標示配置beanid屬性標示給bean起名字class屬性表示給bean定義類型--><bean id="bookDao" class="com.water.dao.impl.BookDaoImpl"></bean><bean id="bookService" class="com.water.server.impl.BookServiceImpl"></bean>
</beans>
(4)首先獲取IOC容器,使用Spring提供的接口完成IOC容器的創建,創建App類,編寫main方法。然后,從容器中獲取對象進行方法調用。
package com.water;import com.water.dao.BookDao;
import com.water.server.impl.BookService;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class App
{public static void main( String[] args ) {// 獲取IOC容器ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");// 獲取beanBookDao bookDao = (BookDao) ctx.getBean("bookDao");bookDao.save();BookService bookService = (BookService) ctx.getBean("bookService");bookService.save();}
}
運行代碼,測試結果為:
Spring的IOC入門案例已經完成,但是在
BookServiceImpl
的類中依然存在BookDaoImpl
對象的new操作,它們之間的耦合度還是比較高,這塊該如何解決,就需要用到下面的DI:依賴注入
。
二、DI入門案例
思路分析
(1)要想實現依賴注入,必須要基于IOC管理Bean
-
DI的入門案例要依賴于前面IOC的入門案例
(2)Service中使用new形式創建的Dao對象是否保留?
-
需要刪除掉,最終要使用IOC容器中的bean對象
(3)Service中需要的Dao對象如何進入到Service中?
-
在Service中提供方法,讓Spring的IOC容器可以通過該方法傳入bean對象
(4)Service與Dao間的關系如何描述?
-
使用配置文件
代碼實現
(1)在BookServiceImpl類中,刪除業務層中使用new的方式創建的dao對象 。在BookServiceImpl類中,為BookDao提供setter方法。
package com.water.server.impl;import com.water.dao.BookDao;
import com.water.dao.impl.BookDaoImpl;
import com.water.server.BookService;public class BookServiceImpl implements BookService {//刪除業務層中使用new的方式創建的dao對象
// private BookDao bookDao = new BookDaoImpl();private BookDao bookDao;public void save() {System.out.println("book service save ...");bookDao.save();}// 為屬性提供setter方法public void setBookDao(BookDao bookDao) {this.bookDao = bookDao;}
}
(2)在配置文件中添加依賴注入的配置,
-
name="bookDao"中
bookDao
的作用是讓Spring的IOC容器在獲取到名稱后,將首字母大寫,前面加set找對應的setBookDao()
方法進行對象注入 -
ref="bookDao"中
bookDao
的作用是讓Spring能在IOC容器中找到id為bookDao
的Bean對象給bookService
進行注入
<?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標簽標示配置beanid屬性標示給bean起名字class屬性表示給bean定義類型--><bean id="bookDao" class="com.water.dao.impl.BookDaoImpl"></bean><bean id="bookService" class="com.water.server.impl.BookServiceImpl"><!--配置server與dao的關系--><!--property標簽表示配置當前bean的屬性name屬性表示配置哪一個具體的屬性ref屬性表示參照哪一個bean--><property name="bookDao" ref="bookDao"></property></bean>
</beans>
(4)運行,測試結果為:
補充:bean基礎配置
(1)bean的基礎配置
對于bean的基礎配置,在前面的案例中已經使用過:
<bean id="" class=""/>
其中,bean標簽的功能、使用方式以及id和class屬性的作用,我們通過一張圖來描述下
(2)bean的別名配置
(3)bean的作用范圍
在Spring配置文件中,配置scope屬性來實現bean的非單例創建,使用bean的scope
屬性可以控制bean的創建是否為單例:
singleton
默認為單例prototype
為非單例
介紹完scope
屬性以后,我們來思考幾個問題:
1)為什么bean默認為單例?
bean為單例的意思是在Spring的IOC容器中只會有該類的一個對象。bean對象只有一個就避免了對象的頻繁創建與銷毀,達到了bean對象的復用,性能高
2)bean在容器中是單例的,會不會產生線程安全問題?
-
如果對象是有狀態對象,即該對象有成員變量可以用來存儲數據的,因為所有請求線程共用一個bean對象,所以會存在線程安全問題。
-
如果對象是無狀態對象,即該對象沒有成員變量沒有進行數據存儲的,因為方法中的局部變量在方法調用完成后會被銷毀,所以不會存在線程安全問題。
3)哪些bean對象適合交給容器進行管理?
-
表現層對象
-
業務層對象
-
數據層對象
-
工具對象
4)哪些bean對象不適合交給容器進行管理?
封裝實例的域對象,因為會引發線程安全問題,所以不適合。
總結
通過前面兩個案例,我們已經學習了bean如何定義配置
,DI如何定義配置
以及容器對象如何獲取
的內容。