1.IOC本質
控制反轉IoC(Inversion of Control),是一種設計思想,DI(依賴注入)是實現IoC的一種方法,也有人認爲DI只是IoC的另一種說法。沒有IoC的程序中 , 我們使用面向對象編程 , 對象的創建與對象間的依賴關係完全硬編碼在程序中,對象的創建由程序自己控制,控制反轉後將對象的創建轉移給第三方,個人認爲所謂控制反轉就是:獲得依賴對象的方式反轉了。
採用XML方式配置Bean的時候,Bean的定義信息是和實現分離的,而採用註解的方式可以把兩者合爲一體,Bean的定義信息直接以註解的形式定義在實現類中,從而達到了零配置的目的。
控制反轉是一種通過描述(XML或註解)並通過第三方去生產或獲取特定對象的方式。在Spring中實現控制反轉的是IoC容器,其實現方法是依賴注入(Dependency Injection,DI)。
2.IOC理論推導
2.1普通的方式
- 先寫一個UserMapper接口
package com.zj.Dao;
public interface UserMapper {
public void getUser();
}
- 再去寫Dao的實現類
package com.zj.Dao;
public class UserMapperImpl implements UserMapper {
public void getUser() {
System.out.println("獲取數據");
}
}
- 然後去寫UserService的接口
package com.zj.service;
public interface UserService {
public void getUser();
}
- 最後寫Service的實現類
package com.zj.service;
import com.zj.Dao.UserMapper;
import com.zj.Dao.UserMapperImpl;
public class UserServiceImpl implements UserService {
private UserMapper userMapper =new UserMapperImpl();
public void getUser() {
userMapper.getUser();
}
}
}
- 測試一下
public class MyTest {
@Test
public void test(){
UserServiceImpl service = new UserServiceImpl();
service.setUserMapper(new UserMapperImpl());
service.getUser();
}
}
- 把UserMapper的實現類增加一個 .
public class UserMapperMySqlImpl implements UserMapper {
public void getUser() {
System.out.println("MySQL數據");
}
}
- 緊接着我們要去使用MySQL的話 , 我們就需要去service實現類裏面修改對應的實現 .
public class UserServiceImpl implements UserService {
private UserMapper userMapper =new UserMapperMySqlImpl();
public void getUser() {
userMapper.getUser();
}
}
}
- 在假設, 我們再增加一個UserMapper的實現類 .
public class UserMapperOracleImpl implements UserMapper {
public void getUser() {
System.out.println("OracleI獲取數據");
}
}
那麼我們要使用Oracle , 又需要去service實現類裏面修改對應的實現 . 假設我們的這種需求非常大 , 這種方式就根本不適用了, 甚至反人類對吧 , 每次變動 , 都需要修改大量代碼 . 這種設計的耦合性太高了, 牽一髮而動全身
那我們如何去解決呢 ?
2.2 修改後的方式
我們可以在需要用到他的地方 , 不去實現它 , 而是留出一個接口 , 利用set , 我們去代碼裏修改如下 .
public class UserServiceImpl implements UserService {
private UserMapper userMapper;
public void setUserMapper(UserMapper userMapper) {
this.userMapper = userMapper;
}
public void getUser() {
userMapper.getUser();
}
}
- 在測試下
public class MyTest {
@Test
public void test(){
UserServiceImpl service = new UserServiceImpl();
/*service.setUserMapper(new UserMapperImpl());
service.getUser();*/
service.setUserMapper(new UserMapperMySqlImpl());
service.getUser();
}
總結:兩種方式對比,我們可以發現以前所有東西都是由程序去進行控制創建 , 而現在是由我們自行控制創建對象 , 把主動權交給了調用者 . 程序不用去管怎麼創建,怎麼實現了 . 它只負責提供一個接口 .
這種思想 , 從本質上解決了問題 , 我們程序員不再去管理對象的創建了 , 更多的去關注業務的實現 . 耦合性大大降低 . 這也就是IOC的原型 !
3、HelloSpring
1. 導入Spring相關jar包
注 : spring 需要導入commons-logging進行日誌記錄 . 我們利用maven , 他會自動下載對應的依賴項 .
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.10.RELEASE</version>
</dependency>
2. 編寫相關代碼
2.1編寫一個Hello實體類
package com.zj.pojo;
public class Hello {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("Hello"+ name );
}
@Override
public String toString() {
return "Hello{" +
"name='" + name + '\'' +
'}';
}
}
2.2 寫編寫我們的spring文件 , 這裏我們命名爲applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="hello" class="com.zj.pojo.Hello">
<property name="name" value="spring"/>
</bean>
</beans>
2.3 我們可以去進行測試了 .
@Test
public void test1(){
ApplicationContext context =new ClassPathXmlApplicationContext("applicationContext.xml");
//getBean : 參數即爲spring配置文件中bean的id .
Hello hello = (Hello) context.getBean("hello");
hello.show();
}
思考問題
-
Hello 對象是誰創建的 ?
hello 對象是由Spring創建的
-
Hello 對象的屬性是怎麼設置的 ?
hello 對象的屬性是由Spring容器設置的 ,
這個過程就叫控制反轉 :
控制 : 誰來控制對象的創建 , 傳統應用程序的對象是由程序本身控制創建的 , 使用Spring後 , 對象是由Spring來創建的 .
反轉 : 程序本身不創建對象 , 而變成被動的接收對象 .
依賴注入 : 就是利用set方法來進行注入的.
IOC是一種編程思想 , 由主動的編程變成被動的接收 .
可以通過newClassPathXmlApplicationContext去瀏覽一下底層源碼 .
OK , 到了現在 , 我們徹底不用再程序中去改動了 , 要實現不同的操作 , 只需要在xml配置文件中進行修改 , 所謂的IOC,一句話搞定 : 對象由Spring 來創建 , 管理 , 裝配 !