Java Web系列:Spring依賴注入基礎,webspring

來源:互聯網
上載者:User

Java Web系列:Spring依賴注入基礎,webspring
一、Spring簡介

1.Spring簡化Java開發

Spring Framework是一個應用程式框架,架構一般是半成品,我們在架構的基礎上可以不用每個項目自己實現架構、基礎設施和常用功能性組件,而是可以專註商務邏輯。因此學習Spring Framework在架構和模式方面的結構和原理,對我們在架構和模組層級別的理解協助極大。Spring Framework(參考1)的宗旨是簡化Java開發,主要的手段如下:

(1)在架構上解耦:通過DI(依賴注入)管理類型依賴,通過AOP分離關注點,減少重複代碼。

(2)在設計上廣泛採用DIP(依賴倒置)和ISP(介面隔離)等原則和Facade(外觀)等模式:提供簡化的調用介面並封裝了眾多出色的第三方組件。

(3)在語言層面上採用註解:通過設定檔和Annotation(參考.NET Attribute)簡化應用配置。

2.Spring Framework的架構和模組:

Spring Framework本身的架構是典型的鬆散分層,外層可以按需引用全部內層,內層不能引用外層。Spring的基礎組件如所示:

可以看出,開始的模組只有從core\beans\aop\context四個組件,後來添加了context-support【1.2】擴充模組、expression【3.0】擴充模組和beans-groovy【4.0】擴充模組。

Spring上述模組的基礎上,內建和封裝了眾多的實用的萬用群組件,主要的組件:

 可以看出,spring-oxm、spring-jdbc和spring-web是眾多模組依賴的核心,spring-oxm提供了Object和XML的映射支援。

二、基礎知識

1.DIP:DIP(依賴倒置原則)是DI(依賴注入)的核心(參考2)。

(1)高層模組不應該依賴於低層模組。兩者都應該依賴於抽象。

(2)抽象不應該依賴於細節。細節應該依賴於抽象。

說人話就是:將對具體類的引用轉換成對其介面的引用,具體類只引用介面(引用==依賴,介面==介面或抽象類別)。事實上我們調用具體類的時候在頭腦裡也是只關心其提供的API而非實現,DIP則通過在設計和重構階段在技術手段上保證瞭解耦。

2.DI:DI(依賴注入)讓我們不必手寫工廠代碼來管理介面和實作類別的映射、對象的建立和生命週期的管理。

(1)介面注入:必須實現特定的介面才可以,侵入性太強,現在已經無人關心和使用。

(2)建構函式注入:依賴體現在建構函式的參數上。

(3)屬性注入:依賴體現在屬性上。

由於在實現時,可以將類型註冊為自己的相容類型,這樣依賴注入就可以直接替代new執行個體化對象,這樣理解和使用依賴注入工具還不如不使用或手寫工廠了。依賴注入工具在實現時肯定會實現成一個支援不同配置和不同生命週期的對象工廠,但即使沒有提供一套添加依賴倒置原則限制的API,也不意味著我們把它當成new的替代品。如同映射工具雖然在實現時可以任意映射,但不是用來取代賦值的,而是用來處理領域實體和視圖模型等有實際對應關係的對象之間的映射。

(1)依賴配置:依賴配置是依賴注入實現的基礎。依賴注入工具都至少支援代碼配置和檔案配置。Java中可以通過Annotation(.NET中通過Attribute)簡化配置。

(2)對象工廠:根據配置返回一個或多個對象。這是核心功能。

(3)生命週期管理:一般提供至少4種層級的支援:範圍、單例、線程、HTTP請求範圍。

大多數依賴注入工具在支援依賴倒置原則的基礎上,在技術手段上實現了更多的功能,如類型的相容轉換、對依賴命名、在配置時直接傳入對象等。

三、Spring依賴注入

Bean在Spring中就是POJO(.NET的POCO),Bean在Spring中就是POJO,Bean在Spring中就是POJO,重要的事情要說3遍。可以簡單的認為Bean就是對象。

Spring依賴注入的核心是BeanFactory和BeanDefinition。分別對應對象工廠和依賴配置的概念。雖然我們通常使用的是ApplicationContext的實作類別,但ApplicationContext只是封裝和擴充了BeanFactory的功能。

雖然說xml配置是Spring依賴注入中支援早、功能強大和容易修改的特點,但xml配置只是Spring依賴注入讀取配置的一種方式,僅此而已。無論以前、現在和以後支援和即將支援什麼樣的配置,Spring依賴注入的核心是BeanDefinition介面,有通過代碼使用BeanDefinition經驗的人可能早就意識到了這一點個:各種配置最後會映射到BeanDefinition。因此我們應該按需使用適合的配置,不要把細枝末節當作核心,至少無論.NET還是Java中,依賴倒置、對象工廠、生命週期等概念是通用的,掌握了這些核心概念,再去學習具體的類庫,會事半功倍。ApplicationContext的實作類別AnnotationConfigWebApplicationContext配合Annotation註解和泛型,早已經提供了更簡易的配置方式。如下代碼所示,現在的Spring依賴注入在使用上已經很接近.NET中的用法了。

現在讓我們關注AnnotationConfigApplicationContext和AnnotationConfigWebApplicationContext。這兩個實作類別是實現無xml配置的核心。

1.Java一般應用程式:

(1)依賴注入代碼:

package me.test.spring_ioc;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class App { public static void main(String[] args) { AnnotationConfigApplicationContext container = new AnnotationConfigApplicationContext(); container.register(AppService.class, Repository.class); container.refresh(); String message = container.getBean(IAppService.class).print(); System.out.println(message); container.close(); }}View Code

(2)介面和實現代碼:

package me.test.spring_ioc;public interface IAppService { String print();}package me.test.spring_ioc;public interface IRepository<T> { String print();}package me.test.spring_ioc;public class SimpleEntity {}package me.test.spring_ioc;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Scope;@Scope("request")public class AppService implements IAppService { private IRepository<SimpleEntity> _repo; @Autowired public AppService(IRepository<SimpleEntity> repo) { this._repo = repo; } @Override public String print() { return this._repo.print(); }}package me.test.spring_ioc;public class Repository<T> implements IRepository<T> { @Override public String print() { return "Test"; }}View Code

從代碼中我們可以看到,不需要設定檔,不需要使用字串,不需要對介面類有任何副作用。

2.Java Web應用程式:

(1)依賴注入代碼:

package swp;import javax.servlet.ServletContext;import javax.servlet.ServletException;import org.springframework.web.WebApplicationInitializer;import org.springframework.web.context.ContextLoaderListener;import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;public class MyWebAppInitializer implements WebApplicationInitializer{ @Override public void onStartup(ServletContext container) throws ServletException { AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); rootContext.register(AppService.class,Repository.class); container.addListener(new ContextLoaderListener(rootContext)); }}View Code

(2)JSP中調用(介面和實現代碼同上):

<%@page import="swp.IAppService"%><%@page import="org.springframework.web.context.WebApplicationContext"%><%@page import=" org.springframework.web.context.support.WebApplicationContextUtils"%><html><body> <% WebApplicationContext context = WebApplicationContextUtils .getRequiredWebApplicationContext(this.getServletContext()); String message = context.getBean(IAppService.class).print(); out.print(message); %></body></html>View Code

隨著Java中泛型和註解的添加以及版本的更新,Spring中包含了眾多的ApplicationContext,從最基礎的ClassPathXmlApplicationContext、FileSystemXmlApplicationContext、XmlWebApplicationContext等實現,又陸續與時俱進的添加了GenericWebApplicationContext【1.2】、XmlPortletApplicationContext【2.0】、ResourceAdapterApplicationContext【2.5】、GenericXmlApplicationContext【3.0】、【AnnotationConfigWebApplicationContext】、GenericGroovyApplicationContext【4.0】、GroovyWebApplicationContext【4.1】。閱讀Spring原始碼是最好的學習方式沒有之一,但如果你只想拷貝一段pom.xml+applicationContext.xml+ClassPathXmlApplicationContext的調用代碼又另當別論。

四、Spring依賴注入的要點

1.BeanFactory的階層

BeanFactory是spring中依賴注入的核心,其設計主要採用了ISP(介面隔離原則),通過多層次的介面繼承即保證了單個介面的內聚又保證了整個體系的簡潔。這裡我們要關注的核心是DefaultListableBeanFactory。

,查看XmlBeanFactory代碼,可以看到XmlBeanFactory只是通過XmlBeanDefinitionReader載入了BeanDefinition配置,XmlBeanDefinitionReader負責將配置解析到BeanDefinition。DefaultListableBeanFactory是真正的實作類別,其中定義了類型為Map<String, BeanDefinition>的beanDefinitionMap列表用於儲存依賴配置。

2.BeanDefinitionReader的階層:

除了上文提到的XmlBeanDefinitionReader,BeanDefinitionReader還有2個實作類別PropertiesBeanDefinitionReader和GroovyBeanDefinitionReader,還有1個單獨定義的AnnotatedBeanDefinitionReader。ApplicationContext的實作類別中,有些是固定搭配這些BeanDefinitionReader,有些沒有沒有綁定BeanDefinitionReader,我們可以通過手動搭配方式,搭配一個或多個BeanDefinitionReader。


3.ApplicationContext的階層

ApplicationContext的各種實作類別太多了,但核心都是將對象工廠功能委託給BeanFactory的實作類別DefaultListableBeanFactory,解析配置都是BeanDefinitionReader的4個相關類。

,各種各樣的ApplicationContext有2個繼承分支。

(1)AbstractRefreshableApplicationContext抽象類別的實作類別:

AbstractRefreshableApplicationContext在refreshBeanFactory中使用了DefaultListableBeanFactory對象並將其作為參數傳遞給loadBeanDefinitions方法。

FileSystemXmlApplicationContext和ClassPathXmlApplicationContext是在基類AbstractXmlApplicationContext實現loadBeanDefinitions方法時使用了XmlBeanDefinitionReader。

XmlWebApplicationContext和XmlPortletApplicationContext使用XmlBeanDefinitionReader,GroovyWebApplicationContext使用的是GroovyBeanDefinitionReader。

AnnotationConfigWebApplicationContext使用的是AnnotatedBeanDefinitionReader。

(2)GenericApplicationContext類及其子類:

GenericApplicationContext沒有和特定的BeanDefinitionReader綁定,我們可以直接使用該類型執行個體作為構造參數傳遞給BeanDefinitionReader,再手動調用BeanDefinitionReader的loadBeanDefinitions方法。這意味著我們可以使用多個BeanDefinitionReader。

GenericGroovyApplicationContext和GenericXmlApplicationContext分別使用了GroovyBeanDefinitionReader和XmlBeanDefinitionReader。

AnnotationConfigApplicationContext使用的是AnnotatedBeanDefinitionReader。

ResourceAdapterApplicationContext和GenericWebApplicationContext和基類GenericApplicationContext一樣,沒有綁定特定的實現。

Spring的依賴注入雖然也有對象工廠和依賴配置的概念,但其依賴配置是以對象為核心而不是類型,BeanDefinition直接對應的是對象的資訊及其依賴,這在通過代碼進行配置的時候有明顯的體現。google guice(參考3)在依賴倒置支援和代碼配置上是明顯優於Spring的。

參考

1.http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/overview.html

2.https://en.wikipedia.org/wiki/Dependency_inversion_principle

3.http://www.ibm.com/developerworks/cn/java/j-guice.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.