溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Spring Context基礎(chǔ)知識(shí)點(diǎn)有哪些

發(fā)布時(shí)間:2021-12-08 14:29:20 來源:億速云 閱讀:193 作者:iii 欄目:大數(shù)據(jù)

本篇內(nèi)容介紹了“Spring Context基礎(chǔ)知識(shí)點(diǎn)有哪些”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

Spring IOC/DI AOP 理解

前言

  作為從事java開發(fā)的碼農(nóng),Spring的重要性不言而喻,你可能每天都在和Spring框架打交道。Spring恰如其名的,給java應(yīng)用程序的開發(fā)帶了春天般的舒爽感覺。Spring,可以說是任何一個(gè)java開發(fā)者通往技術(shù)高階的必備基礎(chǔ)。當(dāng)然,要學(xué)好Spring,尤其是了解Spring的底層原理并不容易,需要花費(fèi)很多時(shí)間和精力來潛心的研習(xí),并在實(shí)際的項(xiàng)目中不斷的試錯(cuò)和總結(jié),才能形成屬于自己的思維理解。博主對(duì)Spring最初的認(rèn)識(shí)頗淺,項(xiàng)目中遇到問題依靠度娘大概也能籠而統(tǒng)之的解決。不過呢,接觸Spring這么一年多時(shí)間里,對(duì)其框架體系認(rèn)知比較雜亂,深層技術(shù)依然是霧里看花一般,沒有形成自己的認(rèn)知和理解,這對(duì)編程技術(shù)的提升是十分不利的。鑒于此,才決定靜下心來從頭至尾系統(tǒng)的學(xué)習(xí)Spring框架,并通過博客的形式記錄學(xué)習(xí)點(diǎn)滴,分享技術(shù)知識(shí),算是拋磚引玉吧。好了,閑言少敘,咱們開始切入正題

Spring框架核心介紹

  DI(Dependency Injection),依賴注入。和我們常聽說的另一個(gè)概念 IOC(控制反轉(zhuǎn))其實(shí)歸根結(jié)底實(shí)現(xiàn)的功能是相同的,只是同樣的功能站在不同的角度來闡述罷了。這里博主就不去過多的辨析,度娘上有一大堆解釋。我們需要知道的是,什么叫依賴注入,為什么要依賴注入。搞清這兩點(diǎn),我想對(duì)Spring的學(xué)習(xí)在思想上就算是上道了。

  在沒用使用Spring的時(shí)候——也就是沒有依賴注入的時(shí)候,java應(yīng)用程序的類與類之間要實(shí)現(xiàn)相互的功能協(xié)作是比較費(fèi)勁的,某個(gè)類(A)要實(shí)現(xiàn)它的功能如果需要依賴另一個(gè)類(B)的協(xié)作的話,就需要在A類中主動(dòng)創(chuàng)建出B類的對(duì)象,才能使用B類的方法完成功能(這里看官就不要去糾結(jié)靜態(tài)方法之類的情況了)。這等于是A類需要負(fù)責(zé)B類對(duì)象整個(gè)生命周期的管理。在極度簡(jiǎn)單的情況下,在一個(gè)類中new出另一個(gè)類的對(duì)象似乎并沒有什么問題,但是復(fù)雜的應(yīng)用程序類與類的協(xié)作關(guān)系往往是多邊的,我們并不知道一個(gè)類功能的實(shí)現(xiàn)會(huì)依賴多少個(gè)另類對(duì)象來協(xié)作,所以在類中自行創(chuàng)建對(duì)象并且管理對(duì)象的整個(gè)生命周期,會(huì)造成代碼的高度耦合以及不可想象的復(fù)雜度。那么,試想,如果我們能將對(duì)象的生命周期交給第三方組件來管理,當(dāng)某個(gè)類需要另外的對(duì)象時(shí)第三方組件就直接創(chuàng)建出來交給它,這樣,類就可以只專注于自己功能的實(shí)現(xiàn),而不用去管理其他類對(duì)象的生命周期,這樣類的功能就單純了很多。

是的,你一定已經(jīng)明白了,Spring(容器)就是這個(gè)第三方組件。我們只需要告訴Spring(容器)有哪些對(duì)象需要管理就行了,不用去關(guān)心Spring框架是如何創(chuàng)建對(duì)象的。這樣,當(dāng)某個(gè)類A需要類B對(duì)象時(shí),如果類B已經(jīng)聲明交給了Sping容器管理,那么在程序運(yùn)行到類A需要類B時(shí),Spring容器就通過依賴注入的方式,將類B對(duì)象注入到類A中協(xié)助完成業(yè)務(wù)功能。通過第三方組件的依賴注入,對(duì)象無需再自行的創(chuàng)建和管理類與類之間的依賴關(guān)系了。對(duì)象的創(chuàng)建依賴注入的方式也有多種,譬如接口注入,構(gòu)造方法注入,setter方法注入等等。說到這里,你對(duì)依賴注入應(yīng)該有比較直白的認(rèn)知了。至于為什么要依賴注入,上文已經(jīng)說得很明白了,就是為了減少代碼中組件之間的耦合度,我們還是先通過簡(jiǎn)單示例來直觀感受下依賴注入比自己管理對(duì)象的好處吧

public class Man implements Human {
    private QQCar car;
    public Man() {
        this.car = new QQCar();
    }
    @Override
    public void xiabibi() {
    }
    public void driveCar(){
        car.drive();
    }
}

 接口Car暫有兩個(gè)實(shí)現(xiàn):奔馳車和QQ車,在以上Man類和QQCar類高度耦合的代碼中,老司機(jī)通過構(gòu)造器只創(chuàng)建了QQ車對(duì)象,所以只能開QQ車,那么老司機(jī)想開奔馳怎么辦呢,你讓他重新創(chuàng)建奔馳車的對(duì)象嗎?這樣高度耦合的代碼似乎是毫無辦法的,那么,我們通過注入對(duì)象的方式對(duì)上述代碼做一番改進(jìn):

public class Man implements Human {
    private Car car; //注意此處哦
    public Man(Car car) {
        this.car = car;
    }
    @Override
    public void xiabibi() {
    }

    public void driveCar() {
        car.drive();
    }
}

以上代碼根據(jù)多態(tài)特性,通過構(gòu)造器接口注入的方式屏蔽掉了具體的對(duì)象實(shí)現(xiàn),這樣,老司機(jī)就能想開什么車就開什么車了。這就是依賴注入帶來的好處。

  AOP(Aspect Oriented Programming),面向切面編程。日常開發(fā)中,我們?cè)谕瓿赡硞€(gè)業(yè)務(wù)功能的時(shí)候,寫了一堆代碼,到最后代碼優(yōu)化的時(shí)候發(fā)現(xiàn),真正完成業(yè)務(wù)的代碼可能就那么兩句,而其余都是與該部分業(yè)務(wù)相關(guān)度不大,僅僅是為了實(shí)現(xiàn)某種技術(shù)的代碼,是完全可以抽離出去的,于是很自然的,我們會(huì)將其抽取成一個(gè)工具類,這樣凡是用到的地方只需調(diào)用一下工具方法就ok了。我們?cè)僬靖咭稽c(diǎn)看,各個(gè)業(yè)務(wù)模塊的功能組件中除了完成相關(guān)的業(yè)務(wù)功能外,都有涉及日志、事務(wù)、安全控制等額外的操作等。這些并不是模塊的核心功能,卻又不可或缺。如果將這些額外功能添加進(jìn)代碼,業(yè)務(wù)系統(tǒng)每個(gè)組件都來一套又顯得太過重復(fù),而且讓業(yè)務(wù)代碼顯得混亂,不夠純粹。

這個(gè)時(shí)候,你問上帝,可不可以讓你的業(yè)務(wù)代碼只專注于業(yè)務(wù)的實(shí)現(xiàn),不去管什么日志、事務(wù)等不相干的東西?喔,上帝說沒問題,于是就有了AOP。如果說依賴注入的目的是讓相互協(xié)作的組件保持一種較為松散的耦合狀態(tài)的話,AOP則是將遍布應(yīng)用各處的功能分離出來形成可重用的組件。通俗點(diǎn)說,日志、事務(wù)等都是可以重用的組件,我們完全可以將分散于業(yè)務(wù)代碼各處的日志、事務(wù)、安全等功能代碼抽離出成為一個(gè)單獨(dú)的工具組件,在Spring的配置中將其進(jìn)行聲明為一個(gè)功能切面,再告訴Spring你想在哪些地方、什么時(shí)機(jī)使用(切入)這些可重用組件就行了。這就是對(duì)面向切面的簡(jiǎn)單釋義。

Spring 容器跟上下文理解

有了Spring之后,通過依賴注入的方式,我們的業(yè)務(wù)代碼不用自己管理關(guān)聯(lián)對(duì)象的生命周期。業(yè)務(wù)代碼只需要按照業(yè)務(wù)本身的流程,走啊走啊,走到哪里,需要另外的對(duì)象來協(xié)助了,就給Spring說,我想要個(gè)對(duì)象 于是Spring就很貼心的給你個(gè)對(duì)象。聽起來似乎很簡(jiǎn)單,使用起來也不難,但是如果僅僅是這樣的拿來主義,倒也灑脫,不用費(fèi)什么腦子。。。可是,你就真的不關(guān)心,Spring是從哪里把對(duì)象給你的嗎?

  如果你想要了解Spring深一些,而不僅僅是拿來用用,那么你就應(yīng)該好好思考一下上訴問題,不然,你還看個(gè)鏟鏟?。∧憧梢赃@樣去思考:Spring既然要負(fù)責(zé)應(yīng)用程序中那么多對(duì)象的創(chuàng)建管理,就像蘋果要生產(chǎn)那么多的手機(jī)(對(duì)象)一樣,肯定有一個(gè)專門搞對(duì)象的地方。蘋果生產(chǎn)手機(jī)的地方叫工廠,比如富士康,但放在軟件開發(fā)中,對(duì)于Spring搞對(duì)象的地方我們就不叫工廠了,而叫做容器。是的,容器的概念在java中你最熟悉的莫過于Tomcat了,它正是一個(gè)運(yùn)行Servlet的web容器,而Spring要想實(shí)現(xiàn)依賴注入功能,就離不開對(duì)象生產(chǎn)的容器——如果沒有容器負(fù)責(zé)對(duì)象的創(chuàng)建管理,你的程序代碼只是喊要對(duì)象了,Spring也無處給你啊。實(shí)際上,容器是Spring框架實(shí)現(xiàn)功能的核心,容器不只是幫我們創(chuàng)建了對(duì)象那么簡(jiǎn)單,它負(fù)責(zé)了對(duì)象整個(gè)的生命周期的管理——?jiǎng)?chuàng)建、裝配、銷毀。關(guān)于Spring的這個(gè)容器你最常聽聞的一個(gè)術(shù)語就是IOC容器。所謂IOC,是一種叫控制反轉(zhuǎn)的編程思想,網(wǎng)上有很通俗易懂的總結(jié),我就不胡亂闡述了。

總之一句話,我的應(yīng)用程序里不用再過問對(duì)象的創(chuàng)建和管理對(duì)象之間的依賴關(guān)系了,都讓IOC容器給代勞吧,也就是說,我把對(duì)象創(chuàng)建、管理的控制權(quán)都交給Spring容器,這是一種控制權(quán)的反轉(zhuǎn),所以Spring容器才能稱為IOC容器。不過這里要清楚一點(diǎn):并不是說只有Spring的容器才叫IOC容器,基于IOC容器的框架還有很多,并不是Spring特有的。

  好了,終于把Spring的容器概念闡述的差不多了,但有什么卵用呢?光有容器你其實(shí)什么都干不了!你以為容器那么科幻,跟叮當(dāng)貓面前的百寶袋一樣,你想要啥它就給你啥?實(shí)際上,容器里面什么都沒有,決定容器里面放什么對(duì)象的是我們自己,決定對(duì)象之間的依賴關(guān)系的,也是我們自己,容器只是給我們提供一個(gè)管理對(duì)象的空間而已。那么,我們?cè)趺聪蛉萜髦蟹湃胛覀冃枰萜鞔鸀楣芾淼膶?duì)象呢?這就涉及到Spring的應(yīng)用上下文了。

什么是應(yīng)用上下文呢,你可以簡(jiǎn)單的理解成就是將你需要Spring幫你管理的對(duì)象放入容器的那么一種。。一種。。額。。一種容器對(duì)象——是的,應(yīng)用上下文即是Spring容器的一種抽象化表述;而我們常見的 ApplicationContext 本質(zhì)上說就是一個(gè)維護(hù)Bean定義以及對(duì)象之間協(xié)作關(guān)系的高級(jí)接口。

應(yīng)用上下文Context :基于 Core 和 Beans,提供了大量的擴(kuò)展,包括國(guó)際化操作(基于 JDK )、資源加載(基于 JDK properties)、數(shù)據(jù)校驗(yàn)(Spring 自己封裝的數(shù)據(jù)校驗(yàn)機(jī)制)、數(shù)據(jù)綁定(Spring 特有,HTTP 請(qǐng)求中的參數(shù)直接映射稱 POJO)、類型轉(zhuǎn)換,ApplicationContext 接口是 Context 的核心,可以理解為Bean的上下文或背景信息。

PS:官方文檔里面對(duì) *Context 相關(guān)的類的描述本來就是通過讀取xml文件中的信息,再通過動(dòng)態(tài)代理生成具體對(duì)象,這里的context狹義上就是指描述類信息的xml文件,實(shí)際這里翻譯為 描述或者周圍環(huán)境配置 更準(zhǔn)確。

這里,我們必須明確,Spring的核心是容器,而容器并不唯一,框架本身就提供了很多個(gè)容器的實(shí)現(xiàn),大概分為兩種類型:一種是不常用的BeanFactory,這是最簡(jiǎn)單的容器,只能提供基本的DI功能;還有一種就是繼承了BeanFactory后派生而來的應(yīng)用上下文,其抽象接口也就是我們上面提到的的ApplicationContext,它能提供更多企業(yè)級(jí)的服務(wù),例如解析配置文本信息等等,這也是應(yīng)用上下文實(shí)例對(duì)象最常見的應(yīng)用場(chǎng)景。有了上下文對(duì)象,我們就能向容器注冊(cè)需要Spring管理的對(duì)象了。對(duì)于上下文抽象接口,Spring也為我們提供了多種類型的容器實(shí)現(xiàn),供我們?cè)诓煌膽?yīng)用場(chǎng)景選擇

  1. AnnotationConfigApplicationContext:從一個(gè)或多個(gè)基于java的配置類中加載上下文定義,適用于java注解的方式;

  2. ClassPathXmlApplicationContext:從類路徑下的一個(gè)或多個(gè)xml配置文件中加載上下文定義,適用于xml配置的方式;

  3. FileSystemXmlApplicationContext:從文件系統(tǒng)下的一個(gè)或多個(gè)xml配置文件中加載上下文定義,也就是說系統(tǒng)盤符中加載xml配置文件;

  4. AnnotationConfigWebApplicationContext:專門為web應(yīng)用準(zhǔn)備的,適用于注解方式;

  5. XmlWebApplicationContext:從web應(yīng)用下的一個(gè)或多個(gè)xml配置文件加載上下文定義,適用于xml配置方式
    Spring Context基礎(chǔ)知識(shí)點(diǎn)有哪些

有了以上理解,問題就很好辦了。你只要將你需要IOC容器替你管理的對(duì)象基于xml也罷,java注解也好,總之你要將需要管理的對(duì)象(Spring中我們都稱之問bean)、bean之間的協(xié)作關(guān)系配置好,然后利用應(yīng)用上下文對(duì)象加載進(jìn)我們的Spring容器,容器就能為你的程序提供你想要的對(duì)象管理服務(wù)了。下面,還是貼一下簡(jiǎn)單的應(yīng)用上下文的應(yīng)用實(shí)例:

  我們先采用xml配置的方式配置bean和建立bean之間的協(xié)作關(guān)系:

<?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-3.2.xsd">
    <bean id="man" class="spring.chapter1.domain.Man">
        <constructor-arg ref="qqCar" />
    </bean>
    <bean  id="qqCar" class="spring.chapter1.domain.QQCar"/>
</beans>

然后通過應(yīng)用上下文將配置加載到IOC容器,讓Spring替我們管理對(duì)象,待我們需要使用對(duì)象的時(shí)候,再從容器中獲取bean就ok了:

public class Test {
    public static void main(String[] args) {
        //加載項(xiàng)目中的spring配置文件到容器
//        ApplicationContext context = new ClassPathXmlApplicationContext("resouces/applicationContext.xml");
        //加載系統(tǒng)盤中的配置文件到容器
        ApplicationContext context = new FileSystemXmlApplicationContext("E:/Spring/applicationContext.xml");
        //從容器中獲取對(duì)象實(shí)例
        Man man = context.getBean(Man.class);
        man.driveCar();
    }
}

以上測(cè)試中,我將配置文件applicationContext.xml分別放在項(xiàng)目中和任意的系統(tǒng)盤符下,我只需要使用相應(yīng)的上下文對(duì)象去加載配置文件,最后的結(jié)果是完全一樣的。當(dāng)然,現(xiàn)在項(xiàng)目中越來越多的使用java注解,所以注解的方式必不可少:

//同xml一樣描述bean以及bean之間的依賴關(guān)系
@Configuration
public class ManConfig {
    @Bean
    public Man man() {
        return new Man(car());
    }
    @Bean
    public Car car() {
        return new QQCar();
    }
}
public class Test {
    public static void main(String[] args) {
        //從java注解的配置中加載配置到容器
        ApplicationContext context = new AnnotationConfigApplicationContext(ManConfig.class);
        //從容器中獲取對(duì)象實(shí)例
        Man man = context.getBean(Man.class);
        man.driveCar();
    }
}

“Spring Context基礎(chǔ)知識(shí)點(diǎn)有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI