天天看點

深度了解SpringIOC,面試你根本不需要慌!

深度了解SpringIOC,面試你還會慌嗎?

文章已托管到GitHub,大家可以去GitHub檢視閱讀,歡迎老闆們前來Star!

搜尋關注微信公衆号 碼出Offer 領取各種學習資料!

深度了解SpringIOC,面試你根本不需要慌!

深度了解Spring IOC(控制反轉)

一、IOC概述

Inverse Of Controll即為控制反轉,簡稱IOC 。

簡單來說,IOC反轉了依賴關系的滿足方式,由之前的自己建立依賴對象,變為由工廠推送。(變主動為被動,即反轉)它解決了具有依賴關系的元件之間的強耦合,使得項目形态更加穩健

二、什麼是IOC?

2.1 了解IOC思想

大概了解了IOC是控制反轉,至于現在我們并不清楚它的思想和作用。那麼問題來了,IOC(控制反轉)是什麼呢?

控制反轉,簡稱IOC。顧名思義,它是由“控制”和“反轉”兩個詞語組合而成。那麼我們就順藤摸瓜,分别分析一下這兩個詞語!

2.2 控制

控制一詞,我們需要想的就很多。比如說,達成控制的條件必須是兩個對象 ,控制可以分為誰控制誰 ,控制你做什麼 。那我們一一列舉這幾種情況:
  1. 在Java中我們以new的方式建立對象,開發者控制控制着開發工具并間接的控制程式建立所需要的依賴對象,對于程式來說是直接的控制建立對象;如果使用IOC呢?那就可以是IOC容器直接的控制建立對象
  2. 既然是IOC控制建立對象,那麼控制建立對象是怎麼控制的呢?使用IOC建立對象是需要标簽引入外部對象,這說明了IOC容器控制着建立依賴對象的入口

2.3 反轉

反轉一詞,我們想的也很多。比如說,達成反轉的條件必須是兩個對象 ,有反轉就有正轉 ,然後就是反轉了些什麼 。那麼我們也一一列舉說明:
  1. 在Java中我們是間接的實用程式來建立對象,這可以看作正轉。那有了IOC容器,一下子就變了,我們不用自己new對象,而是直接反轉為由IOC建立生成依賴對象并存入IOC容器中
  2. 使用IOC容器建立對象我們隻需要通過配置來告訴它需要建立的對象是什麼,并辨別一下以後使用什麼來擷取IOC容器中建立好的對象即可(配置使用IOC的過程),這時候等你想要IOC容器中對象就直接用這個唯一辨別來擷取就好,而擷取的過程肯定是IOC通過這個唯一辨別來查找并傳回給我們該對象
  3. 也許有的小夥伴還是不明白反轉。為什麼要把IOC容器幫我們建立對象的行為叫反轉呢?因為由容器幫我們查找及注入依賴對象,對象隻是被動的接受依賴對象。如果不反轉呢?開發者就需要建立對象,并找到、擷取、使用該對象,此過程中的所有都有開發者來控制的

三、IOC的作用

通過控制反轉,對象在被建立的時候,由一個調控系統内所有對象的外界實體将其所依賴的對象的引用傳遞給它。也可以說,依賴被注入到對象中。

比如:Class A中用到了Class B的對象b,一般情況下,需要在A的代碼中顯式的new一個B的對象。

在使用了IOC之後呢?A的代碼隻需要定義一個私有的B對象,不需要直接new來獲得這個對象,而是通過相關的容器控制程式來将B對象在外部new出來并注入到A類裡的引用中。而具體擷取的方法、對象被擷取時的狀态由配置檔案(xml)來指定

既然由配置檔案來指定建立對象關系,就大大降低了各個元件之間的強耦合并有利于維護,是項目變得更加穩健靈活

四、IOC解決Dao層和Service層的強耦合

在原始的Web開發中,Dao層和Service層是密不可分的。Dao層為資料通路層,隻與資料庫打交道。Servcie層為業務處理層,隻處理實作相應的業務。而我們将Web開發中的Dao層和Service層串在一起,就需要在Service層new一個私有的Dao層實作對象(XxxDaoImpl)。有了IOC的思想,再想想傳統的Dao層與Service層的實作就顯得很不靈活,一旦修改了Dao層實作類,就必須将項目中的源碼都修改掉,顯然是一件非常可怕的事情。

五、使用IOC解決Dao層和Service層的強耦合

既然解決Dao層和Service層的強耦合那必須得這兩個元件對吧。

Dao層

// Dao層接口
package com.mylifes1110.dao;

import com.mylifes1110.bean.User;

public interface UserDao {
    int insertUser(User user);
}

// Dao層實作類
package com.mylifes1110.dao.impl;

import com.mylifes1110.bean.User;
import com.mylifes1110.dao.UserDao;

public class UserDaoImpl implements UserDao {

    @Override
    public int insertUser(User user) {
        System.out.println("------insertUser and UserDao------");
        return 0;
    }
}
           
注意: 我們在使用IOC時,必須将Dao層實作類對象注入到IOC容器中,這必有一個注入方式來告知IOC容器建立對象和擷取對象,在Service層我們并不需要new實作類對象,而是建立一個Service層的Setter方法來注入UserDaoImpl依賴到UserServcieImpl中(這裡可以把它們想為拼裝),此時所用的注入方式叫做Setter方法依賴注入,現在不需要糾結,後續我會将依賴注入的所有方式列舉并分析依賴注入思想和依賴注入與IOC的關系。

Service層

// Service層接口
package com.mylifes1110.service;

import com.mylifes1110.bean.User;

public interface UserService {
    int insertUser(User user);
}

// Service層實作類
package com.mylifes1110.service.impl;

import com.mylifes1110.bean.User;
import com.mylifes1110.dao.UserDao;
import com.mylifes1110.service.UserService;

public class UserServiceImpl implements UserService {
    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public int insertUser(User user) {
        System.out.println("------insertUser and UserService------");
        return userDao.insertUser(null);
    }
}
           

spring-context.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/beans/spring-context.xsd">

    <!--id:唯一辨別 class:需要被建立的目标對象全限定名-->
    <bean id="UserDao" class="com.mylifes1110.dao.impl.UserDaoImpl"/>

    <!--id:唯一辨別 class:需要被建立的目标對象全限定名-->
    <bean id="UserService" class="com.mylifes1110.service.impl.UserServiceImpl">
        <!--Setter方法依賴注入 name:Service層定義的userDao屬性 ref:Dao層bean标簽唯一辨別-->
        <property name="userDao" ref="UserDao"/>
    </bean>

</beans>
           

測試類

/**
* @MethodName insertUser1
* @Param []
* @Description 測試IOC的使用
* @Author Ziph
* @Date 2020/7/12
*/
@Test
public void insertUser1() {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
    UserService userService = (UserService) context.getBean("UserService");
    userService.insertUser(null);
    // 列印結果
    ------insertUser and UserService------
    ------insertUser and UserDao------
}
           

在這裡插入圖檔描述

繼續閱讀