Spring是一個(gè)輕量級Java開(kāi)發(fā)框架,最早有Rod Johnson創(chuàng )建,目的是為了解決企業(yè)級應用開(kāi)發(fā)的業(yè)務(wù)邏輯層和其他各層的耦合問(wèn)題。它是一個(gè)分層的JavaSE/JavaEE full-stack(一站式)輕量級開(kāi)源框架,為開(kāi)發(fā)Java應用程序提供全面的基礎架構支持。Spring負責基礎架構,因此Java開(kāi)發(fā)者可以專(zhuān)注于應用程序的開(kāi)發(fā)。
Spring最根本的使命是解決企業(yè)級應用開(kāi)發(fā)的復雜性,即簡(jiǎn)化Java開(kāi)發(fā)。
Spring可以做很多事情,它為企業(yè)級開(kāi)發(fā)提供給了豐富的功能,但是這些功能的底層都依賴(lài)于它的兩個(gè)核心特性,也就是依賴(lài)注入(dependency injection,DI)和面向切面編程(aspect-oriented programming,AOP)。
為了降低Java開(kāi)發(fā)的復雜性,Spring采取了以下4種關(guān)鍵策略
基于POJO的輕量級和最小侵入性編程;
通過(guò)依賴(lài)注入和面向接口實(shí)現松耦合;
基于切面和慣例進(jìn)行聲明式編程;
通過(guò)切面和模板減少樣板式代碼。
Spring設計目標:
Spring為開(kāi)發(fā)者提供一個(gè)一站式輕量級應用開(kāi)發(fā)平臺;
Spring設計理念:
在JavaEE開(kāi)發(fā)中,支持POJO和JavaBean開(kāi)發(fā)方式,使應用面向接口開(kāi)發(fā),充分支持OO(面向對象)設計方法;Spring通過(guò)IoC容器實(shí)現對象耦合關(guān)系的管理,并實(shí)現依賴(lài)反轉,將對象之間的依賴(lài)關(guān)系交給IoC容器,實(shí)現解耦;
Spring框架的核心:
IoC容器和AOP模塊。通過(guò)IoC容器管理POJO對象以及他們之間的耦合關(guān)系;通過(guò)AOP以動(dòng)態(tài)非侵入的方式增強服務(wù)。
IoC讓相互協(xié)作的組件保持松散的耦合,而AOP編程允許你把遍布于應用各層的功能分離出來(lái)形成可重用的功能組件。
工廠(chǎng)模式:BeanFactory就是簡(jiǎn)單工廠(chǎng)模式的體現,用來(lái)創(chuàng )建對象的實(shí)例;
單例模式:Bean默認為單例模式。
代理模式:Spring的AOP功能用到了JDK的動(dòng)態(tài)代理和CGLIB字節碼生成技術(shù);
模板方法:用來(lái)解決代碼重復的問(wèn)題。比如. RestTemplate, JmsTemplate, JpaTemplate。
觀(guān)察者模式:定義對象鍵一種一對多的依賴(lài)關(guān)系,當一個(gè)對象的狀態(tài)發(fā)生改變時(shí),所有依賴(lài)于它的對象都會(huì )得到通知被制動(dòng)更新,如Spring中listener的實(shí)現–ApplicationListener。
Spring 總共大約有 20 個(gè)模塊, 由 1300 多個(gè)不同的文件構成。 而這些組件被分別整合在核心容器(Core Container) 、 AOP(Aspect Oriented Programming)和設備支持(Instrmentation) 、數據訪(fǎng)問(wèn)與集成(Data Access/Integeration) 、 Web、 消息(Messaging) 、 Test等 幾 個(gè)模塊中。 以下是 Spring 5 的模塊結構圖:

Spring 核心容器
提供了框架的基本組成部分,包括控制反轉(Inversion of Control,IOC)和依賴(lài)注入(Dependency Injection,DI)功能。 它包含以下模塊:
Spring Core
Spring Bean
SpEL (Spring Expression Language)
Spring Context
AOP
該層支持面向切面編程
數據訪(fǎng)問(wèn)/集成
該層提供與數據庫交互的支持。它包含以下模塊:
JDBC (Java DataBase Connectivity)
ORM (Object Relational Mapping)
OXM (Object XML Mappers)
JMS (Java Messaging Service)
Transaction
Web
該層提供了創(chuàng )建 Web 應用程序的支持 。 它包含以下模塊:
Web
Servlet
WSocket
Portlet
Instrumentation
該層為類(lèi)檢測和類(lèi)加載器實(shí)現提供支持。
Test
該層為使用 JUnit 和 TestNG 進(jìn)行測試提供支持。
其他模塊
Messaging
該模塊為 STOMP 提供支持 。 它還支持注解編程模型,該模型用于從
WebSocket
客戶(hù)端路由和處理 STOMP 消息。
Aspects
該模塊為與AspectJ的集成提供支持 。
這是基本的Spring模塊,提供spring 框架的基礎功能,BeanFactory 是 任何以spring為基礎的應用的核心。Spring 框架建立在此模塊之上,它使Spring成為一個(gè)容器。
Bean 工廠(chǎng)是工廠(chǎng)模式的一個(gè)實(shí)現,提供了控制反轉功能,用來(lái)把應用的配置和依賴(lài)從真正的應用代碼中分離。最常用的就是org.springframework.beans.factory.xml.XmlBeanFactory ,它根據XML文件中的定義加載beans。該容器從XML 文件讀取配置元數據并用它去創(chuàng )建一個(gè)完全配置的系統或應用。
Spring 應用一般有以下組件:
接口
定義功能。
Bean 類(lèi)
它包含屬性,setter 和 getter 方法,函數等。
Spring 面向切面編程(AOP)
提供面向切面編程的功能。
Bean 配置文件
包含類(lèi)的信息以及如何配置它們。
用戶(hù)程序
它使用接口
作為一個(gè)成熟的 Spring Web 應用程序。
作為第三方 Web 框架,使用 Spring Frameworks 中間層。
用于遠程使用。
作為企業(yè)級 Java Bean,它可以包裝現有的 POJO(Plain Old Java Objects)。
優(yōu)點(diǎn)
方便解耦,簡(jiǎn)化開(kāi)發(fā)
Spring就是一個(gè)大工廠(chǎng),可以將所有對象的創(chuàng )建和依賴(lài)關(guān)系的維護,交給Spring管理。
AOP編程的支持
Spring提供面向切面編程,可以方便的實(shí)現對程序進(jìn)行權限攔截、運行監控等功能。
聲明式事務(wù)的支持
只需要通過(guò)配置就可以完成對事務(wù)的管理,而無(wú)需手動(dòng)編程。
方便程序的測試
Spring對Junit4支持,可以通過(guò)注解方便的測試Spring程序。
方便集成各種優(yōu)秀框架
Spring不排斥各種優(yōu)秀的開(kāi)源框架,其內部提供了對各種優(yōu)秀框架的直接支持(如:Struts、Hibernate、MyBatis等)。
降低JavaEE API的使用難度
Spring對JavaEE開(kāi)發(fā)中非常難用的一些API(JDBC、JavaMail、遠程調用等),都提供了封裝,使這些API應用難度大大降低。
缺點(diǎn)
Spring明明一個(gè)很輕量級的框架,卻給人感覺(jué)大而全
Spring依賴(lài)反射,反射影響性能
使用門(mén)檻升高,入門(mén)Spring需要較長(cháng)時(shí)間
Spring 提供了以下5種標準的事件:
上下文更新事件(ContextRefreshedEvent):
在調用ConfigurableApplicationContext 接口中的refresh()方法時(shí)被觸發(fā)。
上下文開(kāi)始事件(ContextStartedEvent):
當容器調用ConfigurableApplicationContext的Start()方法開(kāi)始/重新開(kāi)始容器時(shí)觸發(fā)該事件。
上下文停止事件(ContextStoppedEvent):
當容器調用ConfigurableApplicationContext的Stop()方法停止容器時(shí)觸發(fā)該事件。
上下文關(guān)閉事件(ContextClosedEvent):
當ApplicationContext被關(guān)閉時(shí)觸發(fā)該事件。容器被關(guān)閉時(shí),其管理的所有單例Bean都被銷(xiāo)毀。
請求處理事件(RequestHandledEvent):
在Web應用中,當一個(gè)http請求(request)結束觸發(fā)該事件。如果一個(gè)bean實(shí)現了ApplicationListener接口,當一個(gè)ApplicationEvent 被發(fā)布以后,bean會(huì )自動(dòng)被通知。
控制反轉即IoC (Inversion of Control),它把傳統上由程序代碼直接操控的對象的調用權交給容器,通過(guò)容器來(lái)實(shí)現對象組件的裝配和管理。所謂的“控制反轉”概念就是對組件對象控制權的轉移,從程序代碼本身轉移到了外部容器。
Spring IOC 負責創(chuàng )建對象,管理對象(通過(guò)依賴(lài)注入(DI),裝配對象,配置對象,并且管理這些對象的整個(gè)生命周期

管理對象的創(chuàng )建和依賴(lài)關(guān)系的維護。對象的創(chuàng )建并不是一件簡(jiǎn)單的事,在對象關(guān)系比較復雜時(shí),如果依賴(lài)關(guān)系需要程序猿來(lái)維護的話(huà),那是相當頭疼的
解耦,由容器去維護具體的對象
托管了類(lèi)的產(chǎn)生過(guò)程,比如我們需要在類(lèi)的產(chǎn)生過(guò)程中做一些處理,最直接的例子就是代理,如果有容器程序可以把這部分處理交給容器,應用程序則無(wú)需去關(guān)心類(lèi)是如何完成代理的
通常,依賴(lài)注入可以通過(guò)三種方式完成,即:
構造函數注入
setter 注入
接口注入(由于在靈活性和易用性比較差,現在從Spring4開(kāi)始已被廢棄)
Spring 作者 Rod Johnson 設計了兩個(gè)接口用以表示容器。
BeanFactory
ApplicationContext
BeanFactory 簡(jiǎn)單粗暴,可以理解為就是個(gè) HashMap,Key 是 BeanName,Value 是 Bean 實(shí)例。通常只提供注冊(put),獲?。╣et)這兩個(gè)功能。我們可以稱(chēng)之為 “低級容器”。
ApplicationContext 可以稱(chēng)之為 “高級容器”。因為他比 BeanFactory 多了更多的功能。他繼承了多個(gè)接口。因此具備了更多的功能。例如資源的獲取,支持多種消息(例如 JSP tag 的支持),對 BeanFactory 多了工具級別的支持等待。所以你看他的名字,已經(jīng)不是 BeanFactory 之類(lèi)的工廠(chǎng)了,而是 “應用上下文”, 代表著(zhù)整個(gè)大容器的所有功能。該接口定義了一個(gè) refresh 方法,此方法是所有閱讀 Spring 源碼的人的最熟悉的方法,用于刷新整個(gè)容器,即重新加載/刷新所有的 bean。
當然,除了這兩個(gè)大接口,還有其他的輔助接口,這里就不介紹他們了。
BeanFactory和ApplicationContext的關(guān)系
為了更直觀(guān)的展示 “低級容器” 和 “高級容器” 的關(guān)系,這里通過(guò)常用的 ClassPathXmlApplicationContext 類(lèi)來(lái)展示整個(gè)容器的層級 UML 關(guān)系。

看下面的隸屬 ApplicationContext 粉紅色的 “高級容器”,依賴(lài)著(zhù) “低級容器”,這里說(shuō)的是依賴(lài),不是繼承哦。他依賴(lài)著(zhù) “低級容器” 的 getBean 功能。而高級容器有更多的功能:支持不同的信息源頭,可以訪(fǎng)問(wèn)文件資源,支持應用事件(Observer 模式)。
通常用戶(hù)看到的就是 “高級容器”。 但 BeanFactory 也非常夠用啦!
左邊灰色區域的是 “低級容器”, 只負載加載 Bean,獲取 Bean。容器其他的高級功能是沒(méi)有的。例如上圖畫(huà)的 refresh 刷新 Bean 工廠(chǎng)所有配置,生命周期事件回調等。
小結
說(shuō)了這么多,不知道你有沒(méi)有理解Spring IoC? 這里小結一下:IoC 在 Spring 里,只需要低級容器就可以實(shí)現,2 個(gè)步驟:
加載配置文件,解析成 BeanDefinition 放在 Map 里。
調用 getBean 的時(shí)候,從 BeanDefinition 所屬的 Map 里,拿出 Class 對象進(jìn)行實(shí)例化,同時(shí),如果有依賴(lài)關(guān)系,將遞歸調用 getBean 方法 —— 完成依賴(lài)注入。
上面就是 Spring 低級容器(BeanFactory)的 IoC。
至于高級容器 ApplicationContext,他包含了低級容器的功能,當他執行 refresh 模板方法的時(shí)候,將刷新整個(gè)容器的 Bean。同時(shí)其作為高級容器,包含了太多的功能。一句話(huà),他不僅僅是 IoC。他支持不同信息源頭,支持 BeanFactory 工具類(lèi),支持層級容器,支持訪(fǎng)問(wèn)文件資源,支持事件發(fā)布通知,支持接口回調等等。
它將最小化應用程序中的代碼量。
它將使您的應用程序易于測試,因為它不需要單元測試用例中的任何單例
或JNDI 查找機制。
它以最小的影響和最少的侵入機制促進(jìn)松耦合。
它支持即時(shí)的實(shí)例化和延遲加載服務(wù)。
Spring 中的IoC 的實(shí)現原理就是工廠(chǎng)模式加反射機制 。
示例:
interface Fruit { public abstract void eat();}class Apple implements Fruit { public void eat(){ System.out.println("Apple"); }}class Orange implements Fruit { public void eat(){ System.out.println("Orange"); }}class Factory { public static Fruit getInstance(String ClassName) { Fruit f=null; try { f=(Fruit)Class.forName(ClassName).newInstance(); } catch (Exception e) { e.printStackTrace(); } return f; }}class Client { public static void main(String[] a) { Fruit f=Factory.getInstance("com.xxx.xxx.Apple"); if(f!=null){ f.eat(); } }}Spring 的 IoC 設計支持以下功能:
依賴(lài)注入
依賴(lài)檢查
自動(dòng)裝配
支持集合
指定初始化方法和銷(xiāo)毀方法
支持回調某些方法(但是需要實(shí)現 Spring 接口,略有侵入)
其中,最重要的就是依賴(lài)注入,從 XML 的配置上說(shuō),即 ref 標簽。對應 Spring RuntimeBeanReference 對象。
對于 IoC 來(lái)說(shuō),最重要的就是容器。容器管理著(zhù) Bean 的生命周期,控制著(zhù) Bean 的依賴(lài)注入。
BeanFactory和ApplicationContext是Spring的兩大核心接口,都可以當做Spring的容器。其中ApplicationContext是BeanFactory的子接口。
依賴(lài)關(guān)系
BeanFactory:是Spring里面最底層的接口,包含了各種Bean的定義,讀取bean配置文檔,管理bean的加載、實(shí)例化,控制bean的生命周期,維護bean之間的依賴(lài)關(guān)系。
ApplicationContext接口作為BeanFactory的派生,除了提供BeanFactory所具有的功能外,還提供了更完整的框架功能:
繼承MessageSource,因此支持國際化。
統一的資源文件訪(fǎng)問(wèn)方式。
提供在監聽(tīng)器中注冊bean的事件。
同時(shí)加載多個(gè)配置文件。
載入多個(gè)(有繼承關(guān)系)上下文 ,使得每一個(gè)上下文都專(zhuān)注于一個(gè)特定的層次,比如應用的web層。
加載方式
BeanFactroy采用的是延遲加載形式來(lái)注入Bean的,即只有在使用到某個(gè)Bean時(shí)(調用getBean()),才對該Bean進(jìn)行加載實(shí)例化。這樣,我們就不能發(fā)現一些存在的Spring的配置問(wèn)題。如果Bean的某一個(gè)屬性沒(méi)有注入,BeanFacotry加載后,直至第一次使用調用getBean方法才會(huì )拋出異常。
ApplicationContext,它是在容器啟動(dòng)時(shí),一次性創(chuàng )建了所有的Bean。這樣,在容器啟動(dòng)時(shí),我們就可以發(fā)現Spring中存在的配置錯誤,這樣有利于檢查所依賴(lài)屬性是否注入。 ApplicationContext啟動(dòng)后預載入所有的單實(shí)例Bean,通過(guò)預載入單實(shí)例bean ,確保當你需要的時(shí)候,你就不用等待,因為它們已經(jīng)創(chuàng )建好了。
相對于基本的BeanFactory,ApplicationContext 唯一的不足是占用內存空間。當應用程序配置Bean較多時(shí),程序啟動(dòng)較慢。
創(chuàng )建方式
BeanFactory通常以編程的方式被創(chuàng )建,ApplicationContext還能以聲明的方式創(chuàng )建,如使用ContextLoader。
注冊方式
BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但兩者之間的區別是:BeanFactory需要手動(dòng)注冊,而ApplicationContext則是自動(dòng)注冊。
FileSystemXmlApplicationContext :
此容器從一個(gè)XML文件中加載beans的定義,XML Bean 配置文件的全路徑名必須提供給它的構造函數。
ClassPathXmlApplicationContext:
此容器也從一個(gè)XML文件中加載beans的定義,這里,你需要正確設置classpath因為這個(gè)容器將在classpath里找bean配置。
WebXmlApplicationContext:
此容器加載一個(gè)XML文件,此文件定義了一個(gè)WEB應用的所有bean。
控制反轉IoC是一個(gè)很大的概念,可以用不同的方式來(lái)實(shí)現。其主要實(shí)現方式有兩種:依賴(lài)注入和依賴(lài)查找
依賴(lài)注入:相對于IoC而言,依賴(lài)注入(DI)更加準確地描述了IoC的設計理念。所謂依賴(lài)注入(Dependency Injection),即組件之間的依賴(lài)關(guān)系由容器在應用系統運行期來(lái)決定,也就是由容器動(dòng)態(tài)地將某種依賴(lài)關(guān)系的目標對象實(shí)例注入到應用系統中的各個(gè)關(guān)聯(lián)的組件之中。組件不做定位查詢(xún),只提供普通的Java方法讓容器去決定依賴(lài)關(guān)系。
依賴(lài)注入的基本原則是:應用組件不應該負責查找資源或者其他依賴(lài)的協(xié)作對象。配置對象的工作應該由IoC容器負責,“查找資源”的邏輯應該從應用組件的代碼中抽取出來(lái),交給IoC容器負責。容器全權負責組件的裝配,它會(huì )把符合依賴(lài)關(guān)系的對象通過(guò)屬性(JavaBean中的setter)或者是構造器傳遞給需要的對象。
依賴(lài)注入之所以更流行是因為它是一種更可取的方式:讓容器全權負責依賴(lài)查詢(xún),受管組件只需要暴露JavaBean的setter方法或者帶參數的構造器或者接口,使容器可以在初始化時(shí)組裝對象的依賴(lài)關(guān)系。其與依賴(lài)查找方式相比,主要優(yōu)勢為:
查找定位操作與應用代碼完全無(wú)關(guān)。
不依賴(lài)于容器的API,可以很容易地在任何容器以外使用應用對象。
不需要特殊的接口,絕大多數對象可以做到完全不必依賴(lài)容器。
| 構造函數注入 | setter 注入 |
|---|---|
| 沒(méi)有部分注入 | 有部分注入 |
| 不會(huì )覆蓋 setter 屬性 | 會(huì )覆蓋 setter 屬性 |
| 任意修改都會(huì )創(chuàng )建一個(gè)新實(shí)例 | 任意修改不會(huì )創(chuàng )建一個(gè)新實(shí)例 |
| 適用于設置很多屬性 | 適用于設置少量屬性 |
兩種依賴(lài)方式都可以使用,構造器注入和Setter方法注入。最好的解決方案是用構造器參數實(shí)現強制依賴(lài),setter方法實(shí)現可選依賴(lài)。
它們是構成用戶(hù)應用程序主干的對象。
Bean 由 Spring IoC 容器管理。
它們由 Spring IoC 容器實(shí)例化,配置,裝配和管理。
Bean 是基于用戶(hù)提供給容器的配置元數據創(chuàng )建。
基于xml配置
bean 所需的依賴(lài)項和服務(wù)在 XML 格式的配置文件中指定 。 這些配置文件通常包含許多 bean 定義和特定于應用程序的配置選項。 它們通常以 bean 標簽開(kāi)頭。例如:
<bean id="studentbean" class="org.edureka.firstSpring.StudentBean"> <property name="name" value="Edureka"></property></bean>
基于注解配置
您可以通過(guò)在相關(guān)的類(lèi),方法或字段聲明上使用注解,將 bean 配置為組件類(lèi)本身,而不是使用 XML 來(lái)描述 bean 裝配。 默認情況下, Spring 容器中未打開(kāi)注解裝配。 因此,您需要在使用它之前在 Spring 配置文件中啟用它。 例如:
<beans><context:annotation-config/><!-- bean definitions go here --></beans>
基于Java API 配置
Spring的Java配置是通過(guò)使用@Bean和@Configuration來(lái)實(shí)現 。
例如:
@Configurationpublic class StudentConfig { @Bean public StudentBean myStudent() { return new StudentBean(); }}@Bean
注解扮演與
@Configuration 類(lèi)
允許通過(guò)簡(jiǎn)單地調用同一個(gè)類(lèi)中的其他@Bean方法來(lái)定義bean間依賴(lài)關(guān)系。
Spring bean 支持5種scope:
Singleton
每個(gè) Spring IoC 容器僅有一個(gè)單實(shí)例 。
Prototype
每次請求都會(huì )產(chǎn)生一個(gè)新的實(shí)例。
Request
每一次 HTTP 請求都會(huì )產(chǎn)生一個(gè)新的實(shí)例,并且該 bean 僅在當前 HTTP 請求內有效。
Session
每一次 HTTP 請求都會(huì )產(chǎn)生一個(gè)新的 bean,同時(shí)該 bean 僅在當前 HTTP session 內有效。
Global-session
類(lèi)似于標準的 HTTP Session 作用域,不過(guò)它僅僅在基于 portlet 的 web 應用中才有意義 。 Portlet 規范定義了全局 Session 的概念,它被所有構成某個(gè) portlet web 應用的各種不同的 portlet 所共享。 在 global session 作用域中定義的 bean 被限定于全局 portlet Session 的生命周期范圍內。 如果你在 web 中使用 global session 作用域來(lái)標識 bean,那么 web 會(huì )自動(dòng)當成 session 類(lèi)型來(lái)使用。
僅當用戶(hù)使用支持Web的ApplicationContext時(shí),最后三個(gè)才可用 。
spring bean 容器的生命周期流程如下:
1、Spring 容器根據配置中的 bean 定義中實(shí)例化 bean。
2、Spring 使用依賴(lài)注入填充所有屬性,如 bean 中所定義的配置。
3、如果 bean 實(shí)現 BeanNameAware 接口,則工廠(chǎng)通過(guò)傳遞 bean 的 ID 來(lái)調用setBeanName()。
4、如果 bean 實(shí)現 BeanFactoryAware 接口,工廠(chǎng)通過(guò)傳遞自身的實(shí)例來(lái)調用 setBeanFactory()。
5、如果存在與 bean 關(guān)聯(lián)的任何BeanPostProcessors,則調用 preProcessBeforeInitialization() 方法 。
6、如果為 bean 指定了 init 方法(的 init-method 屬性),那么將調用它。
7、最后,如果存在與 bean 關(guān)聯(lián)的任何 BeanPostProcessors,則將調用 postProcessAfterInitialization() 方法。
8、如果 bean 實(shí)現 DisposableBean 接口,當 spring 容器關(guān)閉時(shí),會(huì )調用 destory()。
9、如果為 bean 指定了 destroy 方法(的 destroy-method 屬性),那么將調用它。

只有將 bean 用作另一個(gè) bean 的屬性時(shí),才能將 bean 聲明為內部 bean。為了定義 bean, Spring 的基于 XML 的配置元數據在或 中提供了元素的使用 。 內部 bean 總是匿名的,它們總是作為原型。
例如,假設我們有一個(gè) Student 類(lèi),其中引用了 Person 類(lèi)。 這里我們將只創(chuàng )建一個(gè) Person 類(lèi)實(shí)例并在 Student 中使用它。
Student.java
public class Student { private Person person; //Setters and Getters}Person.java
public class Person { private String name; private String address; //Setters and Getters}bean.xml
<bean id=“StudentBean" class="com.lupf.Student"> <property name="person"> <!--This is inner bean --> <bean class="com.lupf.Person"> <property name="name" value=“Scott"></property> <property name="address" value="Bangalore"></property> </bean> </property></bean>
裝配,或bean裝配是指在Spring容器中把bean組裝到一起,前提是容器需要知道bean的依賴(lài)關(guān)系,如何通過(guò)依賴(lài)注入來(lái)把它們裝配到一起。
在Spring框架中,在配置文件中設定bean的依賴(lài)關(guān)系是一個(gè)很好的機制,Spring 容器能夠自動(dòng)裝配相互合作的bean,這意味著(zhù)容器不需要和配置,能通過(guò)Bean工廠(chǎng)自動(dòng)處理bean之間的協(xié)作。這意味著(zhù) Spring可以通過(guò)向Bean Factory中注入的方式自動(dòng)搞定bean之間的依賴(lài)關(guān)系。自動(dòng)裝配可以設置在每個(gè)bean上,也可以設定在特定的bean上。
Spring容器能夠自動(dòng)裝配bean。也就是說(shuō),可以通過(guò)檢查BeanFactory的內容讓Spring自動(dòng)解析bean的協(xié)作者。
自動(dòng)裝配的不同模式:
no
這是默認設置,表示沒(méi)有自動(dòng)裝配 。 應使用顯式 bean 引用進(jìn)行裝配 。
byName
它根據 bean 的名稱(chēng)注入對象依賴(lài)項 。 它匹配并裝配其屬性與 XML 文件中由相同名稱(chēng)定義的 bean。
byType
它根據類(lèi)型注入對象依賴(lài)項。如 果屬性的類(lèi)型與 XML 文件中的一個(gè) bean 名稱(chēng)匹配,則匹配并裝配屬性。
構造函數
它通過(guò)調用類(lèi)的構造函數來(lái)注入依賴(lài)項 。它有大量的參數 。
autodetect
首先容器嘗試通過(guò)構造函數使用 autowire 裝配,如果不能,則嘗試通過(guò) byType 自動(dòng)裝配。
覆蓋的可能性
您始終可以使用
基本元數據類(lèi)型
簡(jiǎn)單屬性(如原數據類(lèi)型,字符串和類(lèi))無(wú)法自動(dòng)裝配。
模糊特性
自動(dòng)裝配不如顯式裝配精確,如果有可能,建議使用顯式裝配。
使用@Autowired注解來(lái)自動(dòng)裝配指定的bean。在使用@Autowired注解之前需要在Spring配置文件進(jìn)行配置,<context:annotation-config />。
在啟動(dòng)spring IoC時(shí),容器自動(dòng)裝載了一個(gè)AutowiredAnnotationBeanPostProcessor后置處理器,當容器掃描到@Autowied、@Resource或@Inject時(shí),就會(huì )在IoC容器自動(dòng)查找需要的bean,并裝配給該對象的屬性。在使用@Autowired時(shí),首先在容器中查詢(xún)對應類(lèi)型的bean:
如果查詢(xún)結果剛好為一個(gè),就將該bean裝配給@Autowired指定的數據;
如果查詢(xún)的結果不止一個(gè),那么@Autowired會(huì )根據名稱(chēng)來(lái)查找;
如果上述查找的結果為空,那么會(huì )拋出異常。解決方法時(shí),使用required=false。
Spring配置文件是個(gè)XML 文件,這個(gè)文件包含了類(lèi)信息,描述了如何配置它們,以及如何相互調用。
Set方法注入;
構造器注入:
通過(guò)index設置參數的位置;
通過(guò)type設置參數類(lèi)型;
靜態(tài)工廠(chǎng)注入;
實(shí)例工廠(chǎng);
不是,Spring框架中的單例bean不是線(xiàn)程安全的。
spring 中的 bean 默認是單例模式,spring 框架并沒(méi)有對單例 bean 進(jìn)行多線(xiàn)程的封裝處理。
實(shí)際上大部分時(shí)候 spring bean 無(wú)狀態(tài)的(比如 dao 類(lèi)),所有某種程度上來(lái)說(shuō) bean 也是安全的,但如果 bean 有狀態(tài)的話(huà)(比如 view model 對象),那就要開(kāi)發(fā)者自己去保證線(xiàn)程安全了,最簡(jiǎn)單的就是改變 bean 的作用域,把“singleton”變更為“prototype”,這樣請求 bean 相當于 new Bean()了,所以就可以保證線(xiàn)程安全了。
有狀態(tài)就是有數據存儲功能。
無(wú)狀態(tài)就是不會(huì )保存數據。
在一般情況下,只有無(wú)狀態(tài)的Bean才可以在多線(xiàn)程環(huán)境下共享,在Spring中,絕大部分Bean都可以聲明為singleton作用域,因為Spring對一些Bean中非線(xiàn)程安全狀態(tài)采用ThreadLocal進(jìn)行處理,解決線(xiàn)程安全問(wèn)題。
ThreadLocal和線(xiàn)程同步機制都是為了解決多線(xiàn)程中相同變量的訪(fǎng)問(wèn)沖突問(wèn)題。同步機制采用了“時(shí)間換空間”的方式,僅提供一份變量,不同的線(xiàn)程在訪(fǎng)問(wèn)前需要獲取鎖,沒(méi)獲得鎖的線(xiàn)程則需要排隊。而ThreadLocal采用了“空間換時(shí)間”的方式。
ThreadLocal會(huì )為每一個(gè)線(xiàn)程提供一個(gè)獨立的變量副本,從而隔離了多個(gè)線(xiàn)程對數據的訪(fǎng)問(wèn)沖突。因為每一個(gè)線(xiàn)程都擁有自己的變量副本,從而也就沒(méi)有必要對該變量進(jìn)行同步了。ThreadLocal提供了線(xiàn)程安全的共享對象,在編寫(xiě)多線(xiàn)程代碼時(shí),可以把不安全的變量封裝進(jìn)ThreadLocal。
有兩個(gè)重要的bean 生命周期方法:
第一個(gè)是setup :
它是在容器加載bean的時(shí)候被調用。
第二個(gè)方法是 teardown :
它是在容器卸載類(lèi)的時(shí)候被調用。
bean 標簽有兩個(gè)重要的屬性(init-method和destroy-method)。用它們你可以自己定制初始化和注銷(xiāo)方法。它們也有相應的注解(@PostConstruct和@PreDestroy)。
Spring提供以下幾種集合的配置元素:
類(lèi)型用于注入一列值,允許有相同的值。
類(lèi)型用于注入一組值,不允許有相同的值。
類(lèi)型用于注入一組鍵值對,鍵和值都可以為任意類(lèi)型。
類(lèi)型用于注入一組鍵值對,鍵和值都只能為String類(lèi)型。
可以。
基于Java的配置,允許你在少量的Java注解的幫助下,進(jìn)行你的大部分Spring配置而非通過(guò)XML文件。
以@Configuration 注解為例,它用來(lái)標記類(lèi)可以當做一個(gè)bean的定義,被Spring IOC容器使用。
另一個(gè)例子是@Bean注解,它表示此方法將要返回一個(gè)對象,作為一個(gè)bean注冊進(jìn)Spring應用上下文。
@Configurationpublic class StudentConfig { @Bean public StudentBean myStudent() { return new StudentBean(); }}注解裝配在默認情況下是不開(kāi)啟的,為了使用注解裝配,我們必須在Spring配置文件中配置 <context:annotation-config/>元素。
@Component:
這將 java 類(lèi)標記為 bean。它是任何 Spring 管理組件的通用構造型。spring 的組件掃描機制現在可以將其拾取并將其拉入應用程序環(huán)境中。
@Controller:
這將一個(gè)類(lèi)標記為 Spring Web MVC 控制器。標有它的 Bean 會(huì )自動(dòng)導入到 IoC 容器中。
@Service:
此注解是組件注解的特化。它不會(huì )對 @Component 注解提供任何其他行為。您可以在服務(wù)層類(lèi)中使用 @Service 而不是 @Component,因為它以更好的方式指定了意圖。
@Repository:
這個(gè)注解是具有類(lèi)似用途和功能的 @Component 注解的特化。它為 DAO 提供了額外的好處。它將 DAO 導入 IoC 容器,并使未經(jīng)檢查的異常有資格轉換為 Spring DataAccessException。
這個(gè)注解表明bean的屬性必須在配置的時(shí)候設置,通過(guò)一個(gè)bean定義的顯式的屬性值或通過(guò)自動(dòng)裝配,若@Required注解的bean屬性未被設置,容器將拋出BeanInitializationException。示例:
public class Employee { private String name; @Required public void setName(String name){ this.name=name; } public string getName(){ return name; }}@Autowired默認是按照類(lèi)型裝配注入的,默認情況下它要求依賴(lài)對象必須存在(可以設置它required屬性為false)。@Autowired 注解提供了更細粒度的控制,包括在何處以及如何完成自動(dòng)裝配。它的用法和@Required一樣,修飾setter方法、構造器、屬性或者具有任意名稱(chēng)和/或多個(gè)參數的PN方法。
public class Employee { private String name; @Autowired public void setName(String name) { this.name=name; } public string getName(){ return name; }}@Autowired可用于:構造函數、成員變量、Setter方法
@Autowired和@Resource之間的區別
@Autowired默認是按照類(lèi)型裝配注入的,默認情況下它要求依賴(lài)對象必須存在(可以設置它required屬性為false)。
@Resource默認是按照名稱(chēng)來(lái)裝配注入的,只有當找不到與名稱(chēng)匹配的bean才會(huì )按照類(lèi)型來(lái)裝配注入。
當您創(chuàng )建多個(gè)相同類(lèi)型的 bean 并希望僅使用屬性裝配其中一個(gè) bean 時(shí),您可以使用@Qualifier 注解和 @Autowired 通過(guò)指定應該裝配哪個(gè)確切的 bean 來(lái)消除歧義。
@RequestMapping 注解用于將特定 HTTP 請求方法映射到將處理相應請求的控制器中的特定類(lèi)/方法。此注釋可應用于兩個(gè)級別:
類(lèi)級別:
映射請求的 URL
方法級別:
映射 URL
HTTP 請求方法
Spring 通過(guò)提供ORM模塊,支持我們在直接JDBC之上使用一個(gè)對象/關(guān)系映射映射(ORM)工具,Spring 支持集成主流的ORM框架,如Hiberate,JDO和 iBATIS,JPA,TopLink,JDO,OJB 。Spring的事務(wù)管理同樣支持以上所有ORM框架及JDBC。
使用Spring JDBC 框架,資源管理和錯誤處理的代價(jià)都會(huì )被減輕。所以開(kāi)發(fā)者只需寫(xiě)statements 和 queries從數據存取數據,JDBC也可以在Spring框架提供的模板類(lèi)的幫助下更有效地被使用,這個(gè)模板叫JdbcTemplate
通過(guò)使用JDBC抽象和DAO模塊,保證數據庫代碼的簡(jiǎn)潔,并能避免數據庫資源錯誤關(guān)閉導致的問(wèn)題,它在各種不同的數據庫的錯誤信息之上,提供了一個(gè)統一的異常訪(fǎng)問(wèn)層。它還利用Spring的AOP 模塊給Spring應用中的對象提供事務(wù)管理服務(wù)。
Spring DAO(數據訪(fǎng)問(wèn)對象) 使得 JDBC,Hibernate 或 JDO 這樣的數據訪(fǎng)問(wèn)技術(shù)更容易以一種統一的方式工作。這使得用戶(hù)容易在持久性技術(shù)之間切換。它還允許您在編寫(xiě)代碼時(shí),無(wú)需考慮捕獲每種技術(shù)不同的異常。
JdbcTemplate
SimpleJdbcTemplate
NamedParameterJdbcTemplate
SimpleJdbcInsert
SimpleJdbcCall
JdbcTemplate 類(lèi)提供了很多便利的方法解決諸如把數據庫數據轉變成基本數據類(lèi)型或對象,執行寫(xiě)好的或可調用的數據庫操作語(yǔ)句,提供自定義的數據錯誤處理。
在Spring中有兩種方式訪(fǎng)問(wèn)Hibernate:
使用 Hibernate 模板和回調進(jìn)行控制反轉
擴展 HibernateDAOSupport 并應用 AOP 攔截器節點(diǎn)
用Spring的 SessionFactory 調用 LocalSessionFactory。集成過(guò)程分三步:
配置the Hibernate SessionFactory
繼承HibernateDaoSupport實(shí)現一個(gè)DAO
在A(yíng)OP支持的事務(wù)中裝配
Spring支持兩種類(lèi)型的事務(wù)管理:
編程式事務(wù)管理:
這意味你通過(guò)編程的方式管理事務(wù),給你帶來(lái)極大的靈活性,但是難維護。
聲明式事務(wù)管理:
這意味著(zhù)你可以將業(yè)務(wù)代碼和事務(wù)管理分離,你只需用注解和XML配置來(lái)管理事務(wù)。
Spring事務(wù)的本質(zhì)其實(shí)就是數據庫對事務(wù)的支持,沒(méi)有數據庫的事務(wù)支持,spring是無(wú)法提供事務(wù)功能的。真正的數據庫層的事務(wù)提交和回滾是通過(guò)binlog或者redo log實(shí)現的。
Spring事務(wù)的傳播行為說(shuō)的是,當多個(gè)事務(wù)同時(shí)存在的時(shí)候,spring如何處理這些事務(wù)的行為。
PROPAGATION_REQUIRED:
如果當前沒(méi)有事務(wù),就創(chuàng )建一個(gè)新事務(wù),如果當前存在事務(wù),就加入該事務(wù),該設置是最常用的設置。
PROPAGATION_SUPPORTS:
支持當前事務(wù),如果當前存在事務(wù),就加入該事務(wù),如果當前不存在事務(wù),就以非事務(wù)執行。
PROPAGATION_MANDATORY:
支持當前事務(wù),如果當前存在事務(wù),就加入該事務(wù),如果當前不存在事務(wù),就拋出異常。
PROPAGATION_REQUIRES_NEW:
創(chuàng )建新事務(wù),無(wú)論當前存不存在事務(wù),都創(chuàng )建新事務(wù)。
PROPAGATION_NOT_SUPPORTED:
以非事務(wù)方式執行操作,如果當前存在事務(wù),就把當前事務(wù)掛起。
PROPAGATION_NEVER:
以非事務(wù)方式執行,如果當前存在事務(wù),則拋出異常。
PROPAGATION_NESTED:
如果當前存在事務(wù),則在嵌套事務(wù)內執行。如果當前沒(méi)有事務(wù),則按REQUIRED屬性執行。
spring 有五大隔離級別,默認值為 ISOLATION_DEFAULT(使用數據庫的設置),其他四個(gè)隔離級別和數據庫的隔離級別一致:
ISOLATION_DEFAULT:用底層數據庫的設置隔離級別,數據庫設置的是什么我就用什么;
ISOLATION_READ_UNCOMMITTED:未提交讀,最低隔離級別、事務(wù)未提交前,就可被其他事務(wù)讀?。〞?huì )出現幻讀、臟讀、不可重復讀);
ISOLATION_READ_COMMITTED:提交讀,一個(gè)事務(wù)提交后才能被其他事務(wù)讀取到(會(huì )造成幻讀、不可重復讀),SQL server 的默認級別;
ISOLATION_REPEATABLE_READ:可重復讀,保證多次讀取同一個(gè)數據時(shí),其值都和事務(wù)開(kāi)始時(shí)候的內容是一致,禁止讀取到別的事務(wù)未提交的數據(會(huì )造成幻讀),MySQL 的默認級別;
ISOLATION_SERIALIZABLE:序列化,代價(jià)最高最可靠的隔離級別,該隔離級別能防止臟讀、不可重復讀、幻讀。
臟讀 :表示一個(gè)事務(wù)能夠讀取另一個(gè)事務(wù)中還未提交的數據。比如,某個(gè)事務(wù)嘗試插入記錄 A,此時(shí)該事務(wù)還未提交,然后另一個(gè)事務(wù)嘗試讀取到了記錄 A。
不可重復讀 :是指在一個(gè)事務(wù)內,多次讀同一數據。
幻讀 :指同一個(gè)事務(wù)內多次查詢(xún)返回的結果集不一樣。比如同一個(gè)事務(wù) A 第一次查詢(xún)時(shí)候有 n 條記錄,但是第二次同等條件下查詢(xún)卻有 n+1 條記錄,這就好像產(chǎn)生了幻覺(jué)。發(fā)生幻讀的原因也是另外一個(gè)事務(wù)新增或者刪除或者修改了第一個(gè)事務(wù)結果集里面的數據,同一個(gè)記錄的數據內容被修改了,所有數據行的記錄就變多或者變少了。
為不同的事務(wù)API 如 JTA,JDBC,Hibernate,JPA 和JDO,提供一個(gè)不變的編程模式。
為編程式事務(wù)管理提供了一套簡(jiǎn)單的API而不是一些復雜的事務(wù)API
支持聲明式事務(wù)管理。
和Spring各種數據訪(fǎng)問(wèn)抽象層很好得集成。
大多數Spring框架的用戶(hù)選擇聲明式事務(wù)管理,因為它對應用代碼的影響最小,因此更符合一個(gè)無(wú)侵入的輕量級容器的思想。聲明式事務(wù)管理要優(yōu)于編程式事務(wù)管理,雖然比編程式事務(wù)管理(這種方式允許你通過(guò)代碼控制事務(wù))少了一點(diǎn)靈活性。唯一不足地方是,最細粒度只能作用到方法級別,無(wú)法做到像編程式事務(wù)那樣可以作用到代碼塊級別。
OOP(Object-Oriented Programming)面向對象編程,允許開(kāi)發(fā)者定義縱向的關(guān)系,但并適用于定義橫向的關(guān)系,導致了大量代碼的重復,而不利于各個(gè)模塊的重用。
AOP(Aspect-Oriented Programming),一般稱(chēng)為面向切面編程,作為面向對象的一種補充,用于將那些與業(yè)務(wù)無(wú)關(guān),但卻對多個(gè)對象產(chǎn)生影響的公共行為和邏輯,抽取并封裝為一個(gè)可重用的模塊,這個(gè)模塊被命名為“切面”(Aspect),減少系統中的重復代碼,降低了模塊間的耦合度,同時(shí)提高了系統的可維護性??捎糜跈嘞拚J證、日志、事務(wù)處理等。
AOP實(shí)現的關(guān)鍵在于 代理模式,AOP代理主要分為靜態(tài)代理和動(dòng)態(tài)代理。靜態(tài)代理的代表為AspectJ;動(dòng)態(tài)代理則以Spring AOP為代表。
1. AspectJ是靜態(tài)代理的增強,所謂靜態(tài)代理,就是AOP框架會(huì )在編譯階段生成AOP代理類(lèi),因此也稱(chēng)為編譯時(shí)增強,他會(huì )在編譯階段將AspectJ(切面)織入到Java字節碼中,運行的時(shí)候就是增強之后的AOP對象。2. Spring AOP使用的動(dòng)態(tài)代理,所謂的動(dòng)態(tài)代理就是說(shuō)AOP框架不會(huì )去修改字節碼,而是每次運行時(shí)在內存中臨時(shí)為方法生成一個(gè)AOP對象,這個(gè)AOP對象包含了目標對象的全部方法,并且在特定的切點(diǎn)做了增強處理,并回調原對象的方法。
Spring AOP中的動(dòng)態(tài)代理主要有兩種方式,JDK動(dòng)態(tài)代理和CGLIB動(dòng)態(tài)代理:
JDK動(dòng)態(tài)代理只提供接口的代理,不支持類(lèi)的代理。核心InvocationHandler接口和Proxy類(lèi),InvocationHandler 通過(guò)invoke()方法反射來(lái)調用目標類(lèi)中的代碼,動(dòng)態(tài)地將橫切邏輯和業(yè)務(wù)編織在一起;接著(zhù),Proxy利用 InvocationHandler動(dòng)態(tài)創(chuàng )建一個(gè)符合某一接口的的實(shí)例, 生成目標類(lèi)的代理對象。
如果代理類(lèi)沒(méi)有實(shí)現 InvocationHandler 接口,那么Spring AOP會(huì )選擇使用CGLIB來(lái)動(dòng)態(tài)代理目標類(lèi)。CGLIB(Code Generation Library),是一個(gè)代碼生成的類(lèi)庫,可以在運行時(shí)動(dòng)態(tài)的生成指定類(lèi)的一個(gè)子類(lèi)對象,并覆蓋其中特定方法并添加增強代碼,從而實(shí)現AOP。CGLIB是通過(guò)繼承的方式做的動(dòng)態(tài)代理,因此如果某個(gè)類(lèi)被標記為final,那么它是無(wú)法使用CGLIB做動(dòng)態(tài)代理的。
靜態(tài)代理與動(dòng)態(tài)代理區別在于生成AOP代理對象的時(shí)機不同,相對來(lái)說(shuō)AspectJ的靜態(tài)代理方式具有更好的性能,但是AspectJ需要特定的編譯器進(jìn)行處理,而Spring AOP則無(wú)需特定的編譯器處理。
InvocationHandler 的 invoke(Object proxy,Method method,Object[] args):proxy是最終生成的代理實(shí)例; method 是被代理目標實(shí)例的某個(gè)具體方法; args 是被代理目標實(shí)例某個(gè)方法的具體入參, 在方法反射調用時(shí)使用。
將 Advice 應用于目標對象后創(chuàng )建的對象稱(chēng)為代理。在客戶(hù)端對象的情況下,目標對象和代理對象是相同的。
Advice + Target Object = Proxy
切面(Aspect):
切面是通知和切點(diǎn)的結合。通知和切點(diǎn)共同定義了切面的全部?jì)热荨?在Spring AOP中,切面可以使用通用類(lèi)(基于模式的風(fēng)格) 或者在普通類(lèi)中以 @AspectJ 注解來(lái)實(shí)現。
連接點(diǎn)(Join point):
指方法,在Spring AOP中,一個(gè)連接點(diǎn) 總是 代表一個(gè)方法的執行。 應用可能有數以千計的時(shí)機應用通知。這些時(shí)機被稱(chēng)為連接點(diǎn)。連接點(diǎn)是在應用執行過(guò)程中能夠插入切面的一個(gè)點(diǎn)。這個(gè)點(diǎn)可以是調用方法時(shí)、拋出異常時(shí)、甚至修改一個(gè)字段時(shí)。切面代碼可以利用這些點(diǎn)插入到應用的正常流程之中,并添加新的行為。
通知(Advice):
在A(yíng)OP術(shù)語(yǔ)中,切面的工作被稱(chēng)為通知。
切入點(diǎn)(Pointcut):
切點(diǎn)的定義會(huì )匹配通知所要織入的一個(gè)或多個(gè)連接點(diǎn)。我們通常使用明確的類(lèi)和方法名稱(chēng),或是利用正則表達式定義所匹配的類(lèi)和方法名稱(chēng)來(lái)指定這些切點(diǎn)。
引入(Introduction):
引入允許我們向現有類(lèi)添加新方法或屬性。
目標對象(Target Object):
被一個(gè)或者多個(gè)切面(aspect)所通知(advise)的對象。它通常是一個(gè)代理對象。也有人把它叫做 被通知(adviced) 對象。 既然Spring AOP是通過(guò)運行時(shí)代理實(shí)現的,這個(gè)對象永遠是一個(gè) 被代理(proxied) 對象。
織入(Weaving):
織入是把切面應用到目標對象并創(chuàng )建新的代理對象的過(guò)程。在目標對象的生命周期里有多少個(gè)點(diǎn)可以進(jìn)行織入:
編譯期:切面在目標類(lèi)編譯時(shí)被織入。AspectJ的織入編譯器是以這種方式織入切面的。
類(lèi)加載期:切面在目標類(lèi)加載到JVM時(shí)被織入。需要特殊的類(lèi)加載器,它可以在目標類(lèi)被引入應用之前增強該目標類(lèi)的字節碼。AspectJ5的加載時(shí)織入就支持以這種方式織入切面。
運行期:切面在應用運行的某個(gè)時(shí)刻被織入。一般情況下,在織入切面時(shí),AOP容器會(huì )為目標對象動(dòng)態(tài)地創(chuàng )建一個(gè)代理對象。SpringAOP就是以這種方式織入切面。
因為Spring基于動(dòng)態(tài)代理,所以Spring只支持方法連接點(diǎn)。Spring缺少對字段連接點(diǎn)的支持,而且它不支持構造器連接點(diǎn)。方法之外的連接點(diǎn)攔截功能,我們可以利用Aspect來(lái)補充。
關(guān)注點(diǎn)(concern)是應用中一個(gè)模塊的行為,一個(gè)關(guān)注點(diǎn)可能會(huì )被定義成一個(gè)我們想實(shí)現的一個(gè)功能。
橫切關(guān)注點(diǎn)(cross-cutting concern)是一個(gè)關(guān)注點(diǎn),此關(guān)注點(diǎn)是整個(gè)應用都會(huì )使用的功能,并影響整個(gè)應用,比如日志,安全和數據傳輸,幾乎應用的每個(gè)模塊都需要的功能。因此這些都屬于橫切關(guān)注點(diǎn)。
在A(yíng)OP術(shù)語(yǔ)中,切面的工作被稱(chēng)為通知,實(shí)際上是程序執行時(shí)要通過(guò)SpringAOP框架觸發(fā)的代碼段。
Spring切面可以應用5種類(lèi)型的通知:
前置通知(Before):在目標方法被調用之前調用通知功能;
后置通知(After):在目標方法完成之后調用通知,此時(shí)不會(huì )關(guān)心方法的輸出是什么;
返回通知(After-returning ):在目標方法成功執行之后調用通知;
異常通知(After-throwing):在目標方法拋出異常后調用通知;
環(huán)繞通知(Around):通知包裹了被通知的方法,在被通知的方法調用之前和調用之后執行自定義的行為。
同一個(gè)aspect,不同advice的執行順序:
沒(méi)有異常情況下的執行順序:
around before advice
before advice
target method 執行
around after advice
after advice
afterReturning
有異常情況下的執行順序:
around before advice
before advice
target method 執行
around after advice
after advice
afterThrowing:異常發(fā)生
java.lang.RuntimeException: 異常發(fā)生
aspect 由 pointcount 和 advice 組成,切面是通知和切點(diǎn)的結合。 它既包含了橫切邏輯的定義, 也包括了連接點(diǎn)的定義. Spring AOP 就是負責實(shí)施切面的框架, 它將切面所定義的橫切邏輯編織到切面所指定的連接點(diǎn)中.
AOP 的工作重心在于如何將增強編織目標對象的連接點(diǎn)上, 這里包含兩個(gè)工作:
如何通過(guò) pointcut 和 advice 定位到特定的 joinpoint 上
如何在 advice 中編寫(xiě)切面代碼.
可以簡(jiǎn)單地認為, 使用 @Aspect 注解的類(lèi)就是切面.

在這種情況下,切面由常規類(lèi)以及基于XML的配置實(shí)現。
在這種情況下(基于@AspectJ的實(shí)現),涉及到的切面聲明的風(fēng)格與帶有java5標注的普通java類(lèi)一致。
BeanNameAutoProxyCreator
DefaultAdvisorAutoProxyCreator
Metadata autoproxying
聯(lián)系客服