Spring IOC推導(dǎo)與DI構(gòu)造器注入超詳細(xì)講解
了解準(zhǔn)備
什么是Spring?
Spring是一款輕量級(jí)的控制反轉(zhuǎn)(IOC)和面向切面編程(AOP)的非入侵式開源框架
- 2002年Spring的前身interface21發(fā)布,隨后在2004年3月24日正式更名發(fā)布Spring1.0版本
- Spring Frameword締造者 Rod Johnson,悉尼大學(xué)音樂學(xué)博士生
Spring框架主要由七部分組成,分別是 Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 Spring Web MVC
Spring三大核心:IOC控制反轉(zhuǎn)、DI依賴注入、AOP面向切面編程
Spring整合了現(xiàn)有的技術(shù)框架,使這些技術(shù)更加易于使用
Spring官網(wǎng):https://spring.io/
下載地址:https://repo.spring.io/ui/native/release/org/springframework/spring
GitHub地址:https://github.com/spring-projects/spring-framework
maven依賴:
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.18</version> </dependency>
整合MyBatis時(shí)導(dǎo)入
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.3.23</version> </dependency>
IOC思想
引入IOC
準(zhǔn)備Dao層接口和一堆實(shí)現(xiàn)類
public interface UserDao { void getUser(); } public class UserDaoImpl implements UserDao{ public void getUser() { System.out.println("UserDao獲取User成功!"); } } public class UserDaoMySqlImpl implements UserDao{ public void getUser() { System.out.println("UserDaoMySqlImpl獲取User成功!"); } } public class UserDaoOracleImpl implements UserDao{ public void getUser() { System.out.println("UserDaoOracleImpl獲取User成功!"); } }
準(zhǔn)備業(yè)務(wù)層
public interface UserService { void getUser(); } public class UserServiceImpl implements UserService{ private UserDao userDao = new UserDaoImpl; public void getUser() { userDao.getUser(); } }
測試不同UserDao實(shí)現(xiàn)類的getUser方法
public class MyTest { @Test public void testGetUser(){ UserServiceImpl service = new UserServiceImpl(); service.getUser(); } }
可以發(fā)現(xiàn),當(dāng)需要調(diào)用不同UserDao實(shí)現(xiàn)類時(shí),每次都需要區(qū)service中修改UserDao實(shí)例的指向
private UserDao userDao = new UserDaoImpl; private UserDao userDao = new UserDaoOracleImpl; private UserDao userDao = new UserDaoMySqlImpl;
這樣設(shè)計(jì)的耦合性極高,對(duì)程序執(zhí)行的控制權(quán)始終在開發(fā)人員手中,當(dāng)用戶提出不同需求就需要我們不斷去修改UserDao實(shí)例的指向。如果代碼數(shù)量大,那么需要修改的就不止一處,下面在service中注入set方法來動(dòng)態(tài)的獲取不同的UserDao實(shí)例指向
service:
public class UserServiceImpl implements UserService{ private UserDao userDao; // 注入set方法 解耦 public void setUserDao(UserDao userDao){ this.userDao = userDao; } public void getUser() { userDao.getUser(); } }
Test:
public class MyTest { @Test public void testGetUser(){ UserServiceImpl service = new UserServiceImpl(); service.setUserDao(new UserDaoOracleImpl()); service.getUser(); } }
上述示例,就可以動(dòng)態(tài)的去選擇執(zhí)行用戶指定的方法。此處的Test可以看作是一個(gè)servlet,它獲取到用戶的請(qǐng)求之后解析出對(duì)應(yīng)執(zhí)行的方法,再通過service去調(diào)用執(zhí)行,耦合性就降低許多即用戶需求和程序之間的耦合性降低,程序執(zhí)行的控制權(quán)交給用戶。以此完成控制反轉(zhuǎn)IOC
IOC本質(zhì)
IOC的本質(zhì)就是一種控制反轉(zhuǎn)的設(shè)計(jì)思想,它不完全等同于DI,DI(依賴注入)可以理解為實(shí)現(xiàn)IOC的一種方式。
那我的理解其實(shí)是,不能說控制權(quán)交給了用戶,只是我們通過程序編寫可以實(shí)現(xiàn)對(duì)用戶需求的解析。解析出用戶的需求對(duì)應(yīng)程序中所要執(zhí)行的方法即可。不能理解為控制權(quán),只能說用戶具有了主動(dòng)權(quán),并且在代碼層面我們提高了程序的動(dòng)態(tài)特性。
所謂控制反轉(zhuǎn),就是說獲取對(duì)象的不再由程序的硬編碼決定,而是反轉(zhuǎn)到了用戶手中。首先程序會(huì)解析出用戶需求,再動(dòng)態(tài)的獲取相應(yīng)對(duì)象
XML配置Spring
以上述UserDao示例配置
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 將每一個(gè)UserDao的實(shí)現(xiàn)類映射到Spring容器中的bean --> <bean id="mysqlImpl" class="com.mountain.dao.MySqlImpl"/> <bean id="oracleImpl" class="com.mountain.dao.OracleImpl"/> <bean id="userService" class="com.mountain.service.UserServiceImpl"> <property name="userDao" ref="mysqlImpl"/> </bean> </beans>
測試;
@Test public void testGetUser(){ // 獲取spring上下文對(duì)象 ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml"); UserServiceImpl service = (UserServiceImpl) context.getBean("userService"); System.out.println(service.getUser()); }
可以看到,創(chuàng)建對(duì)象不需要再利用new關(guān)鍵字硬編碼,而是完全交給Spring容器進(jìn)行創(chuàng)建,我們?cè)趚ml配置中將每一個(gè)UserDao的實(shí)現(xiàn)類映射到Bean,最后測試?yán)肧pring上下文對(duì)象來獲取映射好的bean實(shí)例
配置細(xì)節(jié):
- property標(biāo)簽name對(duì)應(yīng)類中的字段,value是可以自定義的具體值,ref則是將該字段映射到具體某一個(gè)類上比如引用數(shù)據(jù)類型就會(huì)用到ref配置
- bean中的id要與最終用Spring上下文對(duì)象getBean獲取實(shí)例時(shí)的參數(shù)一致
IOC體現(xiàn):
- 對(duì)象的創(chuàng)建、管理全部交給Spring容器。主動(dòng)權(quán)交給Spring
- 程序不在主動(dòng)的創(chuàng)建對(duì)象,而是被動(dòng)的接收對(duì)象
- 利用set方法注入
IOC創(chuàng)建對(duì)象方式
默認(rèn)創(chuàng)建對(duì)象方式:
// 無參構(gòu)造 public User() { System.out.println("默認(rèn)使用無參構(gòu)造"); } // 測試 ApplicationContext context = new ClassPathXmlApplicationContext("application-Context.xml"); User user = (User) context.getBean("User");
最終打印:默認(rèn)使用無參構(gòu)造,所以在不進(jìn)行任何其他配置的情況下,Spring默認(rèn)創(chuàng)建bean依然走無參構(gòu)造器
public User(String name) {} <bean id="User" class="com.yuqu.pojo.User"> <property name="name" value="情人節(jié)"/> </bean>
如果我們只顯式了有參構(gòu)造,那么無參構(gòu)造被覆蓋之后將會(huì)導(dǎo)致application-Context.xml文件配置的bean編譯直接報(bào)錯(cuò)
使用含參構(gòu)造時(shí)
方式一:
<!-- 方式一:index代表構(gòu)造器參數(shù)索引 --> <bean id="User" class="com.yuqu.pojo.User"> <constructor-arg index="0" value="情人節(jié)"/> </bean>
方式二:
<!-- 方式二:type代表參數(shù)類型 基本數(shù)據(jù)類型用 弊端較大 --> <bean id="User" class="com.yuqu.pojo.User"> <constructor-arg type="java.lang.String" value="圣誕節(jié)"/> </bean>
但是假設(shè)多個(gè)參數(shù)都是java.lang.String那么方式二就是不可取的
方式三:
<!-- 方式三:直接通過參數(shù)名設(shè)置 --> <bean id="User" class="com.yuqu.pojo.User"> <constructor-arg name="name" value="國慶節(jié)"/> </bean>
到此這篇關(guān)于Spring IOC推導(dǎo)與DI構(gòu)造器注入超詳細(xì)講解的文章就介紹到這了,更多相關(guān)Spring IOC推導(dǎo)與DI構(gòu)造器注入內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在SpringBoot中如何利用Redis實(shí)現(xiàn)互斥鎖
當(dāng)我們利用Redis存儲(chǔ)熱點(diǎn)數(shù)據(jù)時(shí),突然就過期失效或者被刪除了,導(dǎo)致大量請(qǐng)求同時(shí)訪問數(shù)據(jù)庫,增加了數(shù)據(jù)庫的負(fù)載,為減輕數(shù)據(jù)庫的負(fù)載我們利用互斥鎖,本文重點(diǎn)介紹在SpringBoot中如何利用Redis實(shí)現(xiàn)互斥鎖,感興趣的朋友一起看看吧2023-09-09Java基礎(chǔ)詳解之集合框架工具Collections
這篇文章主要介紹了Java基礎(chǔ)詳解之集合框架工具Collections,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很好地幫助,需要的朋友可以參考下2021-04-04解決nacos啟動(dòng)報(bào)錯(cuò)Server check fail, please che
這篇文章主要介紹了nacos啟動(dòng) Server check fail, please check server localhost ,port 9848 is available的錯(cuò)誤原因以及解決方法,需要的朋友可以參考下2023-09-09SpringBoot時(shí)區(qū)問題解決以及徹底解決時(shí)差問題
這篇文章主要給大家介紹了關(guān)于SpringBoot時(shí)區(qū)問題解決以及徹底解決時(shí)差問題的相關(guān)資料,spring?boot作為微服務(wù)簡易架構(gòu),擁有其自身的特點(diǎn),快速搭建架構(gòu),簡單快捷,需要的朋友可以參考下2023-08-08java實(shí)現(xiàn)基于SMTP發(fā)送郵件的方法
這篇文章主要介紹了java實(shí)現(xiàn)基于SMTP發(fā)送郵件的方法,實(shí)例分析了java基于SMTP服務(wù)發(fā)送郵件的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07springcloud如何獲取網(wǎng)關(guān)封裝的頭部信息
這篇文章主要介紹了springcloud獲取網(wǎng)關(guān)封裝的頭部信息,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06Java AQS中ReentrantReadWriteLock讀寫鎖的使用
ReentrantReadWriteLock稱為讀寫鎖,它提供一個(gè)讀鎖,支持多個(gè)線程共享同一把鎖。這篇文章主要講解一下ReentrantReadWriteLock的使用和應(yīng)用場景,感興趣的可以了解一下2023-02-02