寫了好久!詳細理解Spring和IoC

點擊藍色「程序員的時光 」關注我 ,標註「星標」,及時閱讀最新技術文章

寫在前面:

小夥伴兒們,你們好!今天咱們開篇學習Spring,仔細解讀核心技術java

我是時光,後續還會持續更新,敬請期待!程序員

思惟導圖:


1,Spring是什麼

 Spring是一個輕量級開源框架,以 IOC(Inverse Of Control:控制反轉)和 AOP(Aspect Oriented Programming:面向切面編程)爲內核,提供了展示層 Spring MVC 和持久層 Spring JDBC 以及業務層事務管理等衆多的企業級應用技術,最爲典型的當屬數據庫事務的使用,還能整合開源世界衆多著名的第三方框架和類庫,應該說Spring框架已經融入到了Java EE的各個開發領域。web

2,Spring的優點

2.1,簡化開發

Spring 就是一個大工廠,能夠將全部對象的建立和依賴關係的維護交給 Spring 容器管理,下降了組件之間的耦合性。spring

2.2,聲明式事務的支持

只須要經過配置就能夠完成對事物的管理,而無須手動編程, 提升開發效率和質量。數據庫

2.3,集成各類優秀框架

Spring接受各類開源框架,其內部提供了對各類優秀框架的直接支持。編程

2.4,AOP 編程的支持

Spring 提供面向切面編程,能夠方便地實現對程序進行權限攔截和運行監控等功能。微信

3,Spring下載

Spring官網:app

https://spring.io/框架

最新開發包及文檔下載地址:編輯器

http://repo.springsource.org/libs-release-local/org/springframework/spring/

下載5.25版本便可

4,Spring環境搭建

4.1,新建普通Maven項目

建好以後命名Spring就能夠了,看一下項目結構:

項目結構圖

4.2,導入相關依賴

這裏麪包括Spring的核心包

 <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

4.3,咱們新建一個HelloWorld類

在Java文件夾下新建類命名爲com.java.test.HelloWorld;

package com.java.test;

public class HelloWorld {
    public void say(){
        System.out.println("Spring 你好!");
    }
}

而後咱們就可讓Spring來管理這個類的實例,經過配置文件applicationContext.xml,Spring能夠很輕鬆地作到。

4.4,Spring配置文件

咱們在resources文件夾下新建一個配置文件applicationContext.xml

<?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"
>


    <!--經過id來直接管理HelloWorld的實例對象-->
    <bean id="helloWorld" class="com.java.test.HelloWorld"></bean>
  
</beans>

4.5,經過Spring來獲取類的對象

咱們新建一個測試類命名爲com.java.service.Test;

package com.java.service;

import com.java.test.HelloWorld;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        //加載配置文件applicationContext.xml
        ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
        //經過id獲取bean,返回一個對象
        HelloWorld helloWorld=(HelloWorld)ac.getBean("helloWorld");
        //調用方法
        helloWorld.say();
    }

}

運行結果:

運行結果

5,深刻理解IoC

IoC(控制反轉:Inverse  of  Control),又稱做依賴注入,是一種重要的面向對象編程的法則來削減計算機程序的耦合問題,也是輕量級的Spring框架的核心。

5.1,先來看幾個關鍵問題

什麼是Spring中的bean?

Spring裏面的bean就相似是定義的一個組件,而這個組件的做用就是實現某個功能的,這裏所定義的bean就至關於給了你一個更爲簡便的方法來調用這個組件去實現你要完成的功能。

什麼是控制反轉?

控制:是容器對bean進行建立、管理。控制bean的整個生命週期。

反轉:咱們是被動接受Spring容器建立的對象,而不是本身主動去控制。

什麼是依賴注入?

DI—Dependency Injection,即依賴注入;

依賴:應用程序依賴IoC容器,在程序運行的時候,應用程序須要IoC容器來提供對象須要的外部資源;

注入:IoC容器注入應用程序的某個對象,注入了其所須要的的外部資源(對象、資源和數據等);

因此說控制反轉是經過依賴注入實現的,其實它們是同一個概念的不一樣角度描述。通俗來講就是IoC是設計思想,DI是實現方式。

5.2,IoC實例講解

咱們來具體實現一下控制反轉的設計思想;比方說業務場景是有一項工做須要A和B兩個測試員來完成:

咱們先建一個類A:

package com.java.service;

public class A {
    public void test(){
        System.out.println("A-測試員");
    }
}

而後工做類Work先讓A來作測試:

package com.java.service;

public class Work {
    public void doTest(){
        //A作測試
        A a=new A();
        a.test();
    }
}

咱們測試一下:

package com.java.test;

import com.java.service.Work;

public class Test {
    public static void main(String[] args) {
        Work work=new Work();
        work.doTest();
    }
}

結果是"A-測試員",沒毛病。咱們分析一下代碼,這我的A和工做Work就是徹底耦合在一塊兒,耦合度高。

若是這個時候讓B測試員來完成工做,那麼代碼的改動就很大,破壞完整性,須要在工做Work類裏面從新new對象而且調用方法。

因而乎,咱們來看看Spring中有沒有更簡單的方式吧!

咱們先來寫一個接口,讓A和B都實現這個接口:

public interface Jiekou {
    public void test();
}

咱們在上述的Work類中把接口的set()方法寫一下:

public class Work {
    private Jiekou jiekou;

    public void setJiekou(Jiekou jiekou) {
        this.jiekou = jiekou;
    }

    public void doTest(){
        jiekou.test();
    }
}

而後就是測試類中的修改:

public class Test {
    public static void main(String[] args) {
        //加載配置文件applicationContext.xml
        ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
        //經過id獲取bean,返回一個對象
        Work work=(Work)ac.getBean("work");
        //調用方法
        work.doTest();
    }
}

其中重要的是applicationContext.xml配置文件:

<?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 id="a" class="com.java.service.A"></bean>

    <bean id="b" class="com.java.service.B"></bean>

    <bean id="work" class="com.java.service.Work">
        <property name="jiekou" ref="b"></property>
    </bean>
  
</beans>

咱們這裏只須要在ref中修改參數值便可決定是A測試員仍是B測試員才參與(這裏的文件詳解咱們下面再說)!很是地方便!

5.3,IoC配置文件詳解

咱們看上面的配置文件,第一段是一些命名空間及其規範的介紹;第二段就是bean的屬性賦值等;

  • id:對象的惟一標識;
  • class:bean的徹底限定名稱,從包名稱到類名稱;
  • property:給屬性賦值, name的名稱取決於 set()方法後面的參數, ref引用具體的值;

5.4,IoC容器的設計使用

咱們來看一下這兩行代碼:

//加載配置文件applicationContext.xml
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
//經過id獲取bean,返回一個對象
Work work=(Work)ac.getBean("work");

要知道咱們並無new這個work對象,是Spring幫咱們建立了這個對象,那又是如何建立的呢?

  • Spring IoC容器設計主要是基於 BeanFactoryApplicationContext兩個接口,其中後者是前者的子接口之一,也就是說 BeanFactory是IoC容器所定義的最底層接口。
  • 在第一行中,咱們用 ApplicationContext的子類 ClassPathXmlApplicationContextclass path中加載配置文件;
  • 在第二行中,能夠獲取到具體的bean了,這裏用的是 getBean()方法來獲取對象,點進去發現是在 BeanFactory.class裏面定義的;這樣就能夠獲取到Spring容器爲咱們建立的對象了。
  • getBean的多個方法是用於獲取給Spring IoC容器的Bean。能夠去看看 BeanFactory的源碼。

5.5,Spring IoC的初始化流程

關於這個初始化流程,咱們須要注意的是,Bean的定義和初始化在Spring IoC容器中是兩大步驟,它是先定義,而後纔是初始化和依賴注入的。Bean的定義分爲3步:

  1. Resource定位,這步是Spring IoC容器根據開發者的配置,尋找用戶定義的bean資源,在Spring開發中,經過XML或者註解方式均可以,而定位的內容也就是bean資源是由用戶提供的。
  2. BeanDefinition的載入,這個時候只是將 Resource定位到的信息保存到 BeanDefinition中,此時並不會建立Bean的實例。
  3. BeanDefinition的註冊,這裏就是將 BeanDefinition的信息發佈到Spring IoC容器中,此時仍舊沒有對應的Bean的實例建立。

作完這三步以後,咱們要對Bean進行初始化,在Spring Bean的配置選項中,還有一個lazy-init屬性,其含義是是否初始化Bean,在默認狀況下,她的默認值是false,也就是Spring IoC默認爲自動初始化Bean,不須要咱們手動操做。若是將其設置爲true,那麼只有當咱們使用Spring IoC容器的getBean方法獲取它時,它纔會進行Bean的初始化,完成依賴注入。

小結

咱們再來總結一下Spring建立對象的過程:

首先經過ApplicationContext這個IoC容器的入口,用它的子類ClassPathXmlApplicationContext從class path中加載配置文件,讀取數據,再用getBean()方法獲取具體的Bean實例。Spring框架會爲咱們建立對象,交給IoC容器管理,這個過程就下降了耦合度。

好了,這期就分享到這裏了,下期繼續來聊聊Bean的做用域,生命週期等以及依賴注入的幾種方式,敬請期待!


好了,今天就先分享到這裏了,下期繼續給你們帶來Spring後續內容!更多幹貨、優質文章,歡迎關注個人原創技術公衆號~



本文分享自微信公衆號 - 程序員的時光(gh_9211ec727426)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索