控制反轉IOCjava
例子:spring
你想吃麪包,這時候有兩種狀況:編程
1 你家附近沒有面包店,你就要本身買原材料本身作麪包(傳統編程模式:須要本身new對象)app
2 你家附近有面包店,那麼你只要把你想要吃的口味告訴店家,一會你就能夠吃到麪包了(控制反轉:本身不new對象,對象由框架交給你)框架
注意:你沒有製做麪包,而是由店家制做麪包,可是徹底符合你的口味測試
控制反轉:就是對象由Spring容器建立和管理,調用者只負責使用,下降耦合度,控制權由調用者轉移到Spring容器,控制權產生了反轉。this
依賴注入:從Spring容器角度來看,Spring容器負責將被依賴對象賦值給調用者的成員變量,至關於爲調用者注入它所依賴的實例。spa
因此,控制反轉是一種經過描述(Spring中能夠是XML文件或註解)並經過第三方去產生或獲取特定對象的方式。設計
Spring中實現控制反轉的是IOC容器,其實現方式是依賴注入(DI)code
IOC容器的設計主要是基於BeanFactory和ApplicationContext兩個接口
applicationContext.xml
<bean id="test" class="dao.TestDaoImpl" />
dao/ITestDao.java(接口)
package dao; public interface ITestDao { public void sayHello(); }
dao/TestDaoImpl.java(實現類)
package dao; public class TestDaoImpl implements ITestDao{ public void sayHello() { // TODO Auto-generated method stub System.out.println("Hello,Study hard!"); } }
test/Tests.java(測試類)
package test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import dao.ITestDao; public class Tests { @Test public void test1() { //初始化spring容器ApplicationContext,加載配置文件 ApplicationContext appCon = new ClassPathXmlApplicationContext("applicationContext.xml"); //經過容器獲取test實例 ITestDao tt = (ITestDao) appCon.getBean("test"); tt.sayHello(); } }
依賴注入(DI):
依賴注入是Spring中實現IOC容器的方法,其做用是在使用spring框架建立對象時動態的將其所依賴的對象或屬性值注入bean組件中
依賴注入一般使用兩種方式實現:構造方法注入和setter方法注入
1.構造方法注入
applicationContext.xml內容
<!-- 將指定類DIServiceImpl配置給spring,讓spring建立其實例 -->
<bean id="myTestDao" class="dao.TestDaoImpl"></bean>
<!-- 使用構造方法注入 -->
<bean id="diService" class="service.DIServiceImpl"> <!-- 將myTestDao注入到DIServiceImpl類的屬性ITestDao上 --> <constructor-arg index="0" ref="myTestDao" /> </bean>
service.IDIService.java
package service; /** * 使用構造方法依賴注入ITestDao接口對象 * * Title: IDIService * * Description: * * @author Ethan * * @date 2019年6月25日 * */ public interface IDIService { public void sayHello(); }
service.DIServiceImpl.java
package service; /** * IDIService接口的實現類 * * Title: DIServiceImpl * * Description: * * @author Ethan * * @date 2019年6月25日 * */ import dao.ITestDao; public class DIServiceImpl implements IDIService{ private ITestDao iTestDao; //構造方法,用於實現依賴注入接口對象iTestDao public DIServiceImpl(ITestDao iTestDao) { super(); this.iTestDao = iTestDao; } public void sayHello() { //調用iTestDao中的sayHello方法 iTestDao.sayHello(); System.out.println("IDIService構造方法注入"); } }
測試類:
test.Tests2.java
package test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import service.IDIService; public class Tests2 { /** * 構造方法注入測試類 * * Title: Test1 * * Description: * * */ @Test public void Test1() { ApplicationContext appCon = new ClassPathXmlApplicationContext("applicationContext.xml"); IDIService ts = (IDIService) appCon.getBean("diService"); ts.sayHello(); } }
運行結果:
Hello,Study hard!
IDIService構造方法注入
2 setter方法注入
在上面的結構中加入service.DIServiceImpl.java
package service; import dao.ITestDao; public class DIServiceImpl1 implements IDIService{ private ITestDao iTestDao; //添加iTestDao的setter方法,用於實現依賴注入 public ITestDao getiTestDao() { return iTestDao; } public void setiTestDao(ITestDao iTestDao) { this.iTestDao = iTestDao; } public void sayHello() { // TODO Auto-generated method stub //調用iTestDao中的sayHello方法 iTestDao.sayHello(); System.out.println("TestDaoImpl setter方法注入"); } }
applicationContext.xml加入
<!-- 使用setter方法的注入 -->
<bean id="testDIService1" class="service.DIServiceImpl1">
<!-- 調用DIServiceImpl1類的setter方法,將myTestDao注入到DIServiceImpl1類的屬性iTestDao上 -->
<property name="iTestDao" ref="myTestDao" />
</bean>
測試類:Tests2.java中加入
/** * 使用setter方式注入測試類 * * Title: Test2 * * Description: * * */ @Test public void Test2() { ApplicationContext appCon = new ClassPathXmlApplicationContext("applicationContext.xml"); IDIService ts = (IDIService) appCon.getBean("testDIService1"); ts.sayHello(); }
運行結果:
Hello,Study hard!
TestDaoImpl setter方法注入
思考:
1 IOC容器的實現方式有哪些?
2 在spring框架中什麼是控制反轉?什麼是依賴注入?使用控制反轉與依賴注入有什麼優勢?
3 spring框架採用java的什麼機制進行依賴注入