天天看點

Spring常見問題

Spring常見問題

    問渠那得清如許?為有源頭活水來。

Spring 是個 java 企業級應用的開源開發架構。Spring 主要用來開發 Java 應用,但是有些擴充是針對建構 J2EE 平台的 web 應用。Spring 架構目标是簡化 Java 企業級應用開發,并通過 POJO 為基礎的程式設計模型促進良好的程式設計習慣。

輕量:Spring 是輕量的,基本的版本大約 2MB。

控制反轉:Spring 通過控制反轉實作了松散耦合,對象們給出它們的依賴,而不是建立或查找依賴的對象們。

面向切面的程式設計(AOP):Spring 支援面向切面的程式設計,并且把應用業務邏輯和系統服務分開。

容器:Spring 包含并管理應用中對象的生命周期和配置。

MVC 架構:Spring 的 WEB 架構是個精心設計的架構,是 Web 架構的一個很好的替代品

事務管理:Spring 提供一個持續的事務管理接口,可以擴充到上至本地事務下至全局事務(JTA)。

異常處理: Spring 提 供 方 便 的 API 把 具 體 技 術 相 關 的 異 常 ( 比 如 由 JDBC ,Hibernate or JDO 抛出的)轉化為一緻的 unchecked 異常。

Core module

Bean module

Context module

Expression Language module

JDBC module

ORM module

OXM module

Java Messaging Service(JMS) module

Transaction module

Web module

Web-Servlet module

Web-Struts module

Web-Portlet module

BeanFactory,這是基本的 Spring 子產品,提供 spring 架構的基礎功能,BeanFactory 是 任何以spring 為基礎的應用的核心。Spring 架構建立在此子產品之上,它使 Spring 成為一個容器。

Bean 工廠是工廠模式的一個實作,提供了控制反轉功能,用來把應用的配置和依賴從正真的應用代碼中分離。最常用的 BeanFactory 實作是 XmlBeanFactory 類。

最常用的就是 org.springframework.beans.factory.xml.XmlBeanFactory ,它根據 XML 檔案中的定義加載 beans。該容器從 XML 檔案讀取配置中繼資料并用它去建立一個完全配置的系統或應用。

AOP 子產品用于發給我們的 Spring 應用做面向切面的開發, 很多支援由 AOP 聯盟提供,這樣就確定了 Spring 和其他 AOP 架構的共通性。這個子產品将中繼資料程式設計引入Spring。

通過使用 JDBC 抽象和 DAO 子產品,保證資料庫代碼的簡潔,并能避免資料庫資源錯誤關閉導緻的問題,它在各種不同的資料庫的錯誤資訊之上,提供了一個統一的異常通路層。它還利用 Spring 的 AOP 子產品給 Spring 應用中的對象提供事務管理服務。

Spring 通過提供 ORM 子產品,支援我們直接在 JDBC 之上使用一個對象/關系映射映射(ORM)工具,Spring 支援內建主流的 ORM 架構,如 Hiberate、JDO 和 iBATIS SQL Maps。Spring 的事務管理同樣支援以上所有 ORM 架構及 JDBC。

Spring 的 WEB 子產品是建構在 application context 子產品基礎之上,提供一個适合web 應用的上下文。這個子產品也包括支援多種面向 web 的任務,如透明地處理多個檔案上傳請求和程式級請求參數的綁定到你的業務對象。它也有對 Jakarta Struts的支援。

Spring 配置檔案是個 XML 檔案,這個檔案包含了類資訊,描述了如何配置它們,以及如何互相調用。

Spring IOC 負責建立對象、管理對象(通過依賴注入 DI)、裝配對象和配置對象,并且管理這些對象的整個生命周期。

IOC 或依賴注入把應用的代碼量降到最低。它使應用容易測試,單元測試不再需要單例和 JNDI 查找機制。最小的代價和最小的侵入性使松散耦合得以實作。IOC 容器支援加載服務時的餓漢式初始化和懶加載。

FileSystemXmlApplicationContext :此容器從一個 XML 檔案中加載 beans的定義,XML Bean 配置檔案的全路徑名必須提供給它的構造函數。

ClassPathXmlApplicationContext:此容器也從一個 XML 檔案中加載 beans的定義,這裡,你需要正确設定 classpath 因為這個容器将在 classpath 裡找bean 配置。

WebXmlApplicationContext:此容器加載一個 XML 檔案,此檔案定義了一個WEB 應用的所有 bean。

Application contexts 提供一種方法處理文本消息,一個通常的做法是加載檔案資源(比如鏡像),它們可以向注冊為監聽器的 bean 釋出事件。另外,在容器或容器内的對象上執行的那些不得不由bean工廠以程式化方式處理的操作,可以在Application contexts 中 以聲明的方式處理 。 Application contexts 實作了MessageSource 接口,該接口的實作以可插拔的方式提供擷取本地化消息的方法。

一個定義了一些功能的接口。

這實作包括屬性,它的 Setter , getter 方法和函數等。

Spring AOP。

Spring 的 XML 配置檔案。

使用以上功能的用戶端程式。

依賴注入,是 IOC 的一個方面,是個通常的概念,它有多種解釋。這概念是說你不用建立對象,而隻需要描述它如何被建立。你不在代碼裡直接組裝你的元件和服務,但是要在配置檔案裡描述哪些元件需要哪些服務,之後一個容器(IOC 容器)負責把他們組裝起來。

構造器依賴注入:構造器依賴注入通過容器觸發一個類的構造器來實作的,該類有一系列參數,每個參數代表一個對其他類的依賴。

Setter 方法注入:Setter 方法注入是容器通過調用無參構造器或無參 static 工廠方法執行個體化 bean 之後,調用該 bean 的 setter 方法,即實作了基于 setter 的依賴注入。

兩種依賴方式都可以使用,構造器注入和 Setter 方法注入。最好的解決方案是用構造器參數實作強制依賴,setter 方法實作可選依賴。

Spring beans 是那些形成 Spring 應用的主幹的 java 對象。它們被 Spring IOC 容器初始化、裝配和管理。這些 beans 通過容器中配置的中繼資料建立。比如,以 XML檔案中<bean/> 的形式定義。

Spring 架構定義的 beans 都是單件 beans。在 bean tag 中有個屬性”singleton”,如果它被賦為 TRUE,bean 就是單件,否則就是一個 prototype bean。預設是TRUE,是以所有在 Spring 架構中的 beans 預設都是單件。

一個 Spring Bean 的定義包含容器必知的所有配置中繼資料,包括如何建立一個bean,它的生命周期詳情及它的依賴。

這裡有三種重要的方法給 Spring 容器提供配置中繼資料。

XML 配置檔案。

基于注解的配置。

基于 java 的配置。

23、如何定義類的作用域?

當定義一個<bean> 在 Spring 裡,我們還能給這個 bean 聲明一個作用域。它可以通過 bean 定義中的 scope 屬性來定義。如,當 Spring 要在需要的時候每次生産一個新的 bean 執行個體,bean 的 scope 屬性被指定為 prototype。另一方面,一個bean每次使用的時候必須傳回同一個執行個體,這個bean的scope屬性必須設為singleton。

Spring 架構支援以下五種 bean 的作用域:

singleton : bean 在每個 Spring ioc 容器中隻有一個執行個體。

prototype:一個 bean 的定義可以有多個執行個體。

request:每次 http 請求都會建立一個 bean,該作用域僅在基于 web 的 SpringApplicationContext 情形下有效。

session:在一個 HTTP Session 中,一個 bean 定義對應一個執行個體。該作用域僅在基于 web 的 Spring ApplicationContext 情形下有效。

global-session:在一個全局的 HTTP Session 中,一個 bean 定義對應一個執行個體。該作用域僅在基于 web 的 Spring ApplicationContext 情形下有效。

預設的 Spring bean 的作用域是 Singleton。

不,Spring 架構中的單例 bean 不是線程安全的。

實作多例參考:javascript:void(0)

Spring 容器 從 XML 檔案中讀取 bean 的定義,并執行個體化 bean。Spring 根據 bean 的定義填充所有的屬性。

如果 bean 實作了 BeanNameAware 接 口 , Spring 傳遞 bean 的 ID 到setBeanName 方法。

如果 Bean 實 現了 BeanFactoryAware 接口 , Spring 傳遞 beanfactory 給setBeanFactory 方法。

如果有任何與bean相關聯的 BeanPostProcessors , Spring會在postProcesserBeforeInitialization()方法内調用它們。

如果 bean 實作 IntializingBean 了,調用它的 afterPropertySet 方法,如果 bean聲明了初始化方法,調用此初始化方法。

如果有BeanPostProcessors和 bean關聯 , 這些 bean 的postProcessAfterInitialization() 方法将被調用。

如果 bean 實作了 DisposableBean,它将調用 destroy()方法。

有兩個重要的 bean 生命周期方法,第一個是 setup , 它是在容器加載 bean 的時候被調用。第二個方法是 teardown 它是在容器解除安裝類的時候被調用。The bean 标簽有兩個重要的屬性(init-method 和 destroy-method)。用它們你可以自己定制初始化和登出方法。它們也有相應的注解( @PostConstruct 和@PreDestroy)。

當一個 bean 僅被用作另一個 bean 的屬性時,它能被聲明為一個内部 bean,為了定義 inner bean,在 Spring 的 基于 XML 的 配置中繼資料中,可以在 <property/>或 <constructor-arg/> 元素内使用<bean/> 元素,内部 bean 通常是匿名的,它們的 Scope 一般是 prototype。

Spring 提供以下幾種集合的配置元素:

<list>類型用于注入一列值,允許有相同的值。

<set> 類型用于注入一組值,不允許有相同的值。

<map> 類型用于注入一組鍵值對,鍵和值都可以為任意類型。

<props>類型用于注入一組鍵值對,鍵和值都隻能為 String 類型。

裝配,或 bean 裝配是指在 Spring 容器中把 bean 組裝到一起,前提是容器需要知道 bean 的依賴關系,如何通過依賴注入來把它們裝配到一起。

Spring 容器能夠自動裝配互相合作的bean,這意味着容器不需要<constructor-arg>和<property>配置,能通過 Bean 工廠自動處理 bean 之間的協作。

有五種自動裝配的方式,可以用來指導 Spring 容器用自動裝配方式來進行依賴注入

no:預設的方式是不進行自動裝配,通過顯式設定 ref 屬性來進行裝配。

byName:通過參數名 自動裝配,Spring 容器在配置檔案中發現 bean 的 autowire屬性被設定成 byname,之後容器試圖比對、裝配和該 bean 的屬性具有相同名字的bean。

byType:通過參數類型自動裝配,Spring 容器在配置檔案中發現 bean 的 autowire屬性被設定成 byType,之後容器試圖比對、裝配和該 bean 的屬性具有相同類型的bean。如果有多個bean 符合條件,則抛出錯誤。

constructor:這個方式類似于 byType, 但是要提供給構造器參數,如果沒有确定的帶參數的構造器參數類型,将會抛出異常。

autodetect:首先嘗試使用 constructor 來自動裝配,如果無法工作,則使用 byType方式。

重寫:你仍需用 <constructor-arg>和 <property> 配置來定義依賴,意味着總要重寫自動裝配。

基本資料類型:你不能自動裝配簡單的屬性,如基本資料類型、String 字元串和類。

模糊特性:自動裝配不如顯式裝配精确,如果有可能,建議使用顯式裝配。

33、可以在 Spring 中注入一個 null 和一個空字元串嗎?

 可以。

基于 Java 的配置,允許你在少量的 Java 注解的幫助下,進行你的大部分 Spring配置而非通過 XML 檔案。

以@Configuration 注解為例,它用來标記類可以當做一個 bean 的定義,被 Spring IOC 容器使用。

另一個例子是@Bean 注解,它表示此方法将要傳回一個對象,作為一個 bean 注冊進 Spring 應用上下文。點選這裡學習 JAVA 幾大元注解。

相對于 XML 檔案,注解型的配置依賴于通過位元組碼中繼資料裝配元件,而非尖括号的聲明。開發者通過在相應的類,方法或屬性上使用注解的方式,直接元件類中進行配置,而不是使用 xml 表述 bean 的裝配關系。

注解裝配在預設情況下是不開啟的,為了使用注解裝配,我們必須在 Spring 配置檔案中配置 <context:annotation-config/>元素。

這個注解表明 bean 的屬性必須在配置的時候設定,通過一個 bean 定義的顯式的屬性值或通過自動裝配,若@Required注解的bean屬性未被設定,容器将抛出BeanInitializationException。

@Autowired 注解提供了更細粒度的控制,包括在何處以及如何完成自動裝配。它的用法和@Required 一樣,修飾 setter 方法、構造器、屬性或者具有任意名稱和/或多個參數的 PN 方法。

當有多個相同類型的bean 卻隻有一個需要自動裝配時,将@Qualifier注解和@Autowire 注解結合使用以消除這種混淆,指定需要裝配的确切的 bean。

使用 SpringJDBC 架構,資源管理和錯誤處理的代價都會被減輕。是以開發者隻需寫 statements 和 queries 從資料存取資料,JDBC 也可以在 Spring 架構提供的模闆類的幫助下更有效地被使用,這個模闆叫 JdbcTemplate。

JdbcTemplate 類提供了很多便利的方法解決諸如把資料庫資料轉變成基本資料類型或對象,執行寫好的或可調用的資料庫操作語句,提供自定義的資料錯誤處理。

Spring 對資料通路對象(DAO)的支援旨在簡化它和資料通路技術如 JDBC,Hibernate or JDO 結合使用。這使我們可以友善切換持久層。編碼時也不用擔心會捕獲每種技術特有的異常。

在 Spring 中有兩種方式通路 Hibernate:控制反轉 Hibernate Template 和 Callback繼承 HibernateDAOSupport 提供一個 AOP 攔截器。

Spring 支援以下 ORM:

Hibernate

iBatis

JPA (Java Persistence API)

TopLink

JDO (Java Data Objects)

OJB

用 Spring 的 SessionFactory 調用 LocalSessionFactory,內建過程分三步:

配置 the Hibernate SessionFactory

繼承 HibernateDaoSupport 實作一個 DAO

在 AOP 支援的事務中裝配

Spring 支援兩種類型的事務管理:

程式設計式事務管理:這意味你通過程式設計的方式管理事務,給你帶來極大的靈活性,但是難維護。

聲明式事務管理:這意味着你可以将業務代碼和事務管理分離,你隻需用注解和 XML配置來管理事務。

它為不同的事務 API 如 JTA,JDBC,Hibernate,JPA 和 JDO,提供一個不變的程式設計模式。

它為程式設計式事務管理提供了一套簡單的 API 而不是一些複雜的事務 API 如它支援聲明式事務管理。

它和 Spring 各種資料通路抽象層很好得內建。

大多數 Spring 架構的使用者選擇聲明式事務管理,因為它對應用代碼的影響最小,是以更符合一個無侵入的輕量級容器的思想。聲明式事務管理要優于程式設計式事務管理,雖然比程式設計式事務管理(這種方式允許你通過代碼控制事務)少了一點靈活性。

面向切面的程式設計,或 AOP, 是一種程式設計技術,允許程式子產品化橫向切割關注點,或橫切典型的責任劃分,如日志和事務管理。

AOP 核心就是切面,它将多個類的通用行為封裝成可重用的子產品,該子產品含有一組API 提供橫切功能。比如,一個日志子產品可以被稱作日志的 AOP 切面。根據需求的不同,一個應用程式可以有若幹切面。在 Spring AOP 中,切面通過帶有@Aspect注解的類實作。

關注點是應用中一個子產品的行為,一個關注點可能會被定義成一個我們想實作的一個功能。

橫切關注點是一個關注點,此關注點是整個應用都會使用的功能,并影響整個應用,比如日志,安全和資料傳輸,幾乎應用的每個子產品都需要的功能。是以這些都屬于橫切關注點。

連接配接點代表一個應用程式的某個位置,在這個位置我們可以插入一個 AOP 切面,它實際上是個應用程式執行 Spring AOP 的位置。

通知是個在方法執行前或執行後要做的動作,實際上是程式執行時要通過SpringAOP 架構觸發的代碼段。

Spring 切面可以應用五種類型的通知:

before:前置通知,在一個方法執行前被調用

after:在方法執行之後調用的通知,無論方法執行是否成功

after-returning:僅當方法成功完成後執行的通知

after-throwing:在方法抛出異常退出時執行的通知

around:在方法執行之前和之後調用的通知

切入點是一個或一組連接配接點,通知将在這些位置執行。可以通過表達式或比對的方式指明切入點。

引入允許我們在已存在的類中增加新的方法和屬性。

被一個或者多個切面所通知的對象。它通常是一個代理對象。也指被通知(advised)對象。

代理是通知目标對象後建立的對象。從用戶端的角度看,代理對象和目标對象是一樣的。

BeanNameAutoProxyCreator

DefaultAdvisorAutoProxyCreator

Metadata autoproxying

織入是将切面和到其他應用類型或對象連接配接或建立一個被通知對象的過程。

織入可以在編譯時,加載時,或運作時完成。

在這種情況下,切面由正常類以及基于 XML 的配置實作。

在這種情況下(基于@AspectJ 的實作),涉及到的切面聲明的風格與帶有 java5 标注的普通 java 類一緻。

問渠那得清如許

為有源頭活水來