springaop源碼
㈠ 怎麼閱讀Spring源碼
准備工作
1. 安裝github:現在spring源代碼都在github管理,所以首先需要下載githup,下;
2. 安裝gradle構建工具: 下載完後進行解壓到任意盤符,然後增加環境變數GRADLE_HOME,並在環境變數bin中增加%GRADLE_HOME%/bin,打開DOS窗口,運行gradle -v,出現版本號等信息,表示安裝成功;
3. 下載Spring源碼:首先打開git shell,切換到你的工作目錄,然後輸入以下命令:git clone git://github.com/SpringSource/Spring-framework.git,後面一串是源碼下載地址。大概半小時的樣子,就可以下載完成,這時候在你的工作目錄中就會出現Spring-framework的目錄,裡面有Spring各組件的源碼包;
4. 構建導入:下載下來的代碼不能直接導入Eclipse,要先轉換成Eclipse能讀取的形式。因為所有組件都會依賴spring-core,所有我們首先要轉換Spring-core工程,在命令窗口切換到Spring-core工程,運行gradle cleanidea eclipse命令,我們會看到開始下載工程所依賴的jar包,幾分鍾後執行完畢,再來看Spring-core文件夾,多了.classpath、.project等文件,這是Eclipse工程所必須的,然後可以把他導入到eclipse。因為大部分Spring組件都會用到 spring-beans、spring-context、spring-aop,而他們又依賴spring-expression、spring-instrument,所以我們乾脆先把這些工程都進行轉換並導入eclipse。
我初次導入過程並不順利,拿spring-core為例,其中以來的一個jar包是Spring-framework/spring-core/build/libs/spring-asm-repack-4.0.jar,但我工程裡面並沒有他,只好在網上下載了一個,並加入構建路徑,其次我還發現少commons-pool-1.5.3.jar、spring-cglib-repack-3.0.jar,都一一下載,最後還是報錯沒有java.util.concurrent.ForkJoinPool類,發現這個版本必須使用jdk1.7以上,1.6沒有這個包。折騰半天,終於幾個工程沒變異錯誤了,向前邁進了一步。
㈡ spring的ioc和aop都是什麼
什麼是IoC
Ioc—Inversion of
Control,即「控制反轉」,不是什麼技術,而是一種設計思想。在Java開發中,Ioc意味著將你設計好的對象交給容器控制,而不是傳統的在你的對象內部直接控制。如何理解好Ioc呢?理解好Ioc的關鍵是要明確「誰控制誰,控制什麼,為何是反轉(有反轉就應該有正轉了),哪些方面反轉了」,那我們來深入分析一下:
控制是什麼:傳統Java
SE程序設計,我們直接在對象內部通過new進行創建對象,是程序主動去創建依賴對象;而IoC是有專門一個容器來創建這些對象,即由Ioc容器來控制對象的創建;誰控制誰?當然是IoC
容器控制了對象;控制什麼?那就是主要控制了外部資源獲取(不只是對象包括比如文件等)。
為何是反轉,哪些方面反轉了:有反轉就有正轉,傳統應用程序是由我們自己在對象中主動控制去直接獲取依賴對象,也就是正轉;而反轉則是由容器來幫忙創建及注入依賴對象;為何是反轉?因為由容器幫我們查找及注入依賴對象,對象只是被動的接受依賴對象,所以是反轉;哪些方面反轉了?依賴對象的獲取被反轉了。
IoC能做什麼
IoC不是一種技術,只是一種思想,一個重要的面向對象編程的法則,它能指導我們如何設計出松耦合、更優良的程序。傳統應用程序都是由我們在類內部主動創建依賴對象,從而導致類與類之間高耦合,難於測試;有了IoC容器後,把創建和查找依賴對象的控制權交給了容器,由容器進行注入組合對象,所以對象與對象之間是鬆散耦合,這樣也方便測試,利於功能復用,更重要的是使得程序的整個體系結構變得非常靈活。
其實IoC對編程帶來的最大改變不是從代碼上,而是從思想上,發生了「主從換位」的變化。應用程序原本是老大,要獲取什麼資源都是主動出擊,但是在IoC/DI思想中,應用程序就變成被動的了,被動的等待IoC容器來創建並注入它所需要的資源了。
IoC和DI
DI—Dependency
Injection,即「依賴注入」:是組件之間依賴關系由容器在運行期決定,形象的說,即由容器動態的將某個依賴關系注入到組件之中。依賴注入的目的並非為軟體系統帶來更多功能,而是為了提升組件重用的頻率,並為系統搭建一個靈活、可擴展的平台。通過依賴注入機制,我們只需要通過簡單的配置,而無需任何代碼就可指定目標需要的資源,完成自身的業務邏輯,而不需要關心具體的資源來自何處,由誰實現。
註:如果想要更加深入的了解IoC和DI,請參考大師級人物Martin Fowler的一篇經典文章《Inversion of Control
Containers and the Dependency Injection
pattern》,原文地址:http://www.martinfowler.com/articles/injection.html。
AOP:面向切面編程
什麼是AOP:
概念:在軟體業,AOP為Aspect Oriented
Programming的縮寫,意為:面向切面編程,通過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術。AOP是OOP的延續,是軟體開發中的一個熱點,也是Spring框架中的一個重要內容,是函數式編程的一種衍生范型。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發的效率。(網路)
簡單的說:就是將程序中重復的代碼抽取出來,在需要執行的時候,使用動態代理的技術,在不修改源碼的基礎上,對我們的已有方法進行增強。
AOP的作用和優勢:
作用:從定義中來看,就是為了在程序運行期間,不修改源碼對已有方法進行增強。
優勢:減少重復代碼 提交了開發效率 維護方便
實現方式: 就是動態代理的技術
具體的作用:實現事務的控制 日誌 和 安全模塊
想系統的學習編程可以來我這看看,希望對您有所幫助!~
㈢ 如何理解Spring的AOP
Spring的AOP面向切面編程,就是橫向的,比如程序運行時都要建日誌,相當於SQL的觸發器。
Spring是一個開放源代碼的設計層面框架,他解決的是業務邏輯層和其他各層的松耦合問題,因此它將面向介面的編程思想貫穿整個系統應用。Spring是於2003 年興起的一個輕量級的Java 開發框架,由Rod Johnson創建。簡單來說,Spring是一個分層的JavaSE/EEfull-stack(一站式)輕量級開源框架。
㈣ 如何查看spring源碼
1.准備工作:在官網上下載了Spring源代碼之後,導入Eclipse,以方便查詢。
2.打開我們使用Spring的項目工程,找到Web.xml這個網站系統配置文件,在其中找到Spring的初始化信息:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
由配置信息可知,我們開始的入口就這里ContextLoaderListener這個監聽器。
在源代碼中我們找到了這個類,它的定義是:
public class ContextLoaderListener extends ContextLoader
implements ServletContextListener {
…
/**
* Initialize the root web application context.
*/
public void contextInitialized(ServletContextEvent event) {
this.contextLoader = createContextLoader();
if (this.contextLoader == null) {
this.contextLoader = this;
}
this.contextLoader.initWebApplicationContext(event.getServletContext());
}
...
}
該類繼續了ContextLoader並實現了監聽器,關於Spring的信息載入配置、初始化便是從這里開始了,具體其他閱讀另外寫文章來深入了解。
二、關於IOC和AOP
關於Spring IOC 網上很多相關的文章可以閱讀,那麼我們從中了解到的知識點是什麼?
1)IOC容器和AOP切面依賴注入是Spring是核心。
IOC容器為開發者管理對象之間的依賴關系提供了便利和基礎服務,其中Bean工廠(BeanFactory)和上下文(ApplicationContext)就是IOC的表現形式。BeanFactory是個介面類,只是對容器提供的最基本服務提供了定義,而DefaultListTableBeanFactory、XmlBeanFactory、ApplicationContext等都是具體的實現。
介面:
public interface BeanFactory {
//這里是對工廠Bean的轉義定義,因為如果使用bean的名字檢索IOC容器得到的對象是工廠Bean生成的對象,
//如果需要得到工廠Bean本身,需要使用轉義的名字來向IOC容器檢索
String FACTORY_BEAN_PREFIX = "&";
//這里根據bean的名字,在IOC容器中得到bean實例,這個IOC容器就象一個大的抽象工廠,用戶可以根據名字得到需要的bean
//在Spring中,Bean和普通的JAVA對象不同在於:
//Bean已經包含了我們在Bean定義信息中的依賴關系的處理,同時Bean是已經被放到IOC容器中進行管理了,有它自己的生命周期
Object getBean(String name) throws BeansException;
//這里根據bean的名字和Class類型來得到bean實例,和上面的方法不同在於它會拋出異常:如果根名字取得的bean實例的Class類型和需要的不同的話。
Object getBean(String name, Class requiredType) throws BeansException;
//這里提供對bean的檢索,看看是否在IOC容器有這個名字的bean
boolean containsBean(String name);
//這里根據bean名字得到bean實例,並同時判斷這個bean是不是單件,在配置的時候,默認的Bean被配置成單件形式,如果不需要單件形式,需要用戶在Bean定義信息中標注出來,這樣IOC容器在每次接受到用戶的getBean要求的時候,會生成一個新的Bean返回給客戶使用 - 這就是Prototype形式
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
//這里對得到bean實例的Class類型
Class getType(String name) throws NoSuchBeanDefinitionException;
//這里得到bean的別名,如果根據別名檢索,那麼其原名也會被檢索出來
String[] getAliases(String name);
}
實現:
XmlBeanFactory的實現是這樣的:
public class XmlBeanFactory extends DefaultListableBeanFactory {
//這里為容器定義了一個默認使用的bean定義讀取器,在Spring的使用中,Bean定義信息的讀取是容器初始化的一部分,但是在實現上是和容器的注冊以及依賴的注入是分開的,這樣可以使用靈活的 bean定義讀取機制。
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
//這里需要一個Resource類型的Bean定義信息,實際上的定位過程是由Resource的構建過程來完成的。
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
//在初始化函數中使用讀取器來對資源進行讀取,得到bean定義信息。這里完成整個IOC容器對Bean定義信息的載入和注冊過程
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws
BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
㈤ spring源碼深度解析這本書怎麼樣
您好,希望以下回答能幫助您
《SPRING技術內幕——深入解析SPRING架構與設計原理》
該書講了spring的ioc容器原理,在xml的spring配置文件中,對象是如何解析並生成的。
spring的aop,面向切面編程。這兩塊是比較重要的,屬於核心部分。
其他的如spring mvc ,spring jdbc與hibernate,ibatise集成,spring事務,spring security,
spring 任務調度都有介紹。
大體來說,屬於跟著代碼走向,一個類一個類介紹了一下。其實代碼都是有英文注釋的。
跟著作都的思路看過來也還是可以的,最好是對照類圖分析。
如您還有疑問可繼續追問。
㈥ 讀過完整Spring源碼的來領分
不為領分,談點個人看法
不要過於急於掌握,先明白什麼是spring,spring的本質是什麼,對象間關系,為什麼要通過IoC這樣的方式來管理。
學習資料:
spring2.0中文手冊 http://www.redsaga.com/spring_ref/2.0/html/
推薦書籍:expert one-on-one J2EE Development without EJB 有中文版
//-------------------------
// www.1x3x.net/blog
//-------------------------
㈦ [事物唯一性]spring AOP 事物回滾不同步
總結-spring事物同步回滾/提交:
1.保證事物傳播機制正確配置
2.session會話管理配置
3.DataAccess層異常是否拋出,如果拋出,service也需要拋出(throw e),要麼全不拋,要麼全拋,直至Web層catch().
4.保證拋出的異常是否在spring aop事物管理范圍內,RuntimeException異常,UncheckException異常。如自定義異常需繼承運行時異常。在拋出。
5.如service層需拋出自定義異常,異常又不為運行時異常,需織入一個檢查異常,spring默認只處理RuntimeException的子類和Error,自定義異常需transactionAttribute節點底下定義你自己的rollback rules才能被Spring正確管理,源碼:RuleBasedTransactionAttribute。
問題解決。
㈧ Spring整合rabbitmq實踐(一):基礎
Spring整合rabbitmq實踐(二):擴展
Spring整合rabbitmq實踐(三):源碼
procer:消息生產者;
consumer:消息消費者;
queue:消息隊列;
exchange:接收procer發送的消息按照binding規則轉發給相應的queue;
binding:exchange與queue之間的關系;
virtualHost:每個virtualHost持有自己的exchange、queue、binding,用戶只能在virtualHost粒度控制許可權。
fanout:
群發到所有綁定的queue;
direct:
根據routing key routing到相應的queue,routing不到任何queue的消息扔掉;可以不同的key綁到同一個queue,也可以同一個key綁到不同的queue;
topic:
類似direct,區別是routing key是由一組以「.」分隔的單片語成,可以有通配符,「*」匹配一個單詞,「#」匹配0個或多個單詞;
headers:
根據arguments來routing。
arguments為一組key-value對,任意設置。
「x-match」是一個特殊的key,值為「all」時必須匹配所有argument,值為「any」時只需匹配任意一個argument,不設置默認為「all」。
通過以下配置,可以獲得最基礎的發送消息到queue,以及從queue接收消息的功能。
這個包同時包含了一些其它的包:spring-context、spring-tx、spring-web、spring-messaging、spring-retry、spring-amqp、amqp-client,如果想單純一點,可以單獨引入。
最主要的是以下幾個包,
spring-amqp:
spring-rabbit:
amqp-client:
個人理解就是,spring-amqp是spring整合的amqp,spring-rabbit是spring整合的rabbitmq(rabbitmq是amqp的一個實現,所以可能spring-rabbit也是類似關系),amqp-client提供操作rabbitmq的java api。
目前最新的是2.0.5.RELEASE版本。如果編譯報錯,以下信息或許能有所幫助:
(1)
解決方案:spring-amqp版本改為2.0.5.RELEASE。
(2)
解決方案:spring-context版本改為5.0.7.RELEASE。
(3)
解決方案:spring-core版本改為5.0.7.RELEASE。
(4)
解決方案:spring-beans版本改為5.0.7.RELEASE。
(5)
解決方案:spring-aop版本改為5.0.7.RELEASE。
總之,需要5.0.7.RELEASE版本的spring,及相匹配版本的amqp-client。
後面所講的這些bean配置,spring-amqp中都有默認配置,如果不需要修改默認配置,則不用人為配置這些bean。後面這些配置也沒有涉及到所有的屬性。
這里的ConnectionFactory指的是spring-rabbit包下面的ConnectionFactory介面,不是amqp-client包下面的ConnectionFactory類。
上面這個bean是spring-amqp的核心,不論是發送消息還是接收消息都需要這個bean,下面描述一下裡面這些配置的含義。
setAddresses :設置了rabbitmq的地址、埠,集群部署的情況下可填寫多個,「,」分隔。
setUsername :設置rabbitmq的用戶名。
setPassword :設置rabbitmq的用戶密碼。
setVirtualHost :設置virtualHost。
setCacheMode :設置緩存模式,共有兩種, CHANNEL 和 CONNECTION 模式。
CHANNEL 模式,程序運行期間ConnectionFactory會維護著一個Connection,所有的操作都會使用這個Connection,但一個Connection中可以有多個Channel,操作rabbitmq之前都必須先獲取到一個Channel,否則就會阻塞(可以通過setChannelCheckoutTimeout()設置等待時間),這些Channel會被緩存(緩存的數量可以通過setChannelCacheSize()設置);
CONNECTION 模式,這個模式下允許創建多個Connection,會緩存一定數量的Connection,每個Connection中同樣會緩存一些Channel,除了可以有多個Connection,其它都跟CHANNEL模式一樣。
這里的Connection和Channel是spring-amqp中的概念,並非rabbitmq中的概念,官方文檔對Connection和Channel有這樣的描述:
關於 CONNECTION 模式中,可以存在多個Connection的使用場景,官方文檔的描述:
setChannelCacheSize :設置每個Connection中(注意是每個Connection)可以緩存的Channel數量,注意只是緩存的Channel數量,不是Channel的數量上限,操作rabbitmq之前(send/receive message等)要先獲取到一個Channel,獲取Channel時會先從緩存中找閑置的Channel,如果沒有則創建新的Channel,當Channel數量大於緩存數量時,多出來沒法放進緩存的會被關閉。
注意,改變這個值不會影響已經存在的Connection,隻影響之後創建的Connection。
setChannelCheckoutTimeout :當這個值大於0時, channelCacheSize 不僅是緩存數量,同時也會變成數量上限,從緩存獲取不到可用的Channel時,不會創建新的Channel,會等待這個值設置的毫秒數,到時間仍然獲取不到可用的Channel會拋出AmqpTimeoutException異常。
同時,在 CONNECTION 模式,這個值也會影響獲取Connection的等待時間,超時獲取不到Connection也會拋出AmqpTimeoutException異常。
setPublisherReturns、setPublisherConfirms :procer端的消息確認機制(confirm和return),設為true後開啟相應的機制,後文詳述。
官方文檔描述publisherReturns設為true打開return機制,publisherComfirms設為true打開confirm機制,但測試結果(2.0.5.RELEASE版本)是,任意一個設為true,兩個都會打開。
addConnectionListener、addChannelListener、setRecoveryListener :添加或設置相應的Listener,後文詳述。
setConnectionCacheSize :僅在 CONNECTION 模式使用,設置Connection的緩存數量。
setConnectionLimit :僅在 CONNECTION 模式使用,設置Connection的數量上限。
上面的bean配置,除了需要注入的幾個listener bean以外,其它設置的都是其默認值(2.0.5.RELEASE版本),後面的bean示例配置也是一樣,部分屬性不同版本的默認值可能有所不同。
一般不用配置這個bean,這里簡單提一下。
這個ConnectionFactory是rabbit api中的ConnectionFactory類,這裡面是連接rabbitmq節點的Connection配置。
如果想修改這些配置,可以按如下方式配置:
consumer端如果通過@RabbitListener註解的方式接收消息,不需要這個bean。
不建議直接通過ConnectionFactory獲取Channel操作rabbitmq,建議通過amqpTemplate操作。
setConnectionFactory :設置spring-amqp的ConnectionFactory。
setRetryTemplate :設置重試機制,詳情見後文。
setMessageConverter :設置MessageConverter,用於java對象與Message對象(實際發送和接收的消息對象)之間的相互轉換,詳情見後文。
setChannelTransacted :打開或關閉Channel的事務,關於amqp的事務後文描述。
setReturnCallback、setConfirmCallback :return和confirm機制的回調介面,後文詳述。
setMandatory :設為true使ReturnCallback生效。
這個bean僅在consumer端通過@RabbitListener註解的方式接收消息時使用,每一個@RabbitListener註解的方法都會由這個創建一個MessageListenerContainer,負責接收消息。
setConnectionFactory :設置spring-amqp的ConnectionFactory。
setMessageConverter :對於consumer端,MessageConverter也可以在這里配置。
setAcknowledgeMode :設置consumer端的應答模式,共有三種:NONE、AUTO、MANUAL。
NONE,無應答,這種模式下rabbitmq默認consumer能正確處理所有發出的消息,所以不管消息有沒有被consumer收到,有沒有正確處理都不會恢復;
AUTO,由Container自動應答,正確處理發出ack信息,處理失敗發出nack信息,rabbitmq發出消息後將會等待consumer端的應答,只有收到ack確認信息才會把消息清除掉,收到nack信息的處理辦法由setDefaultRequeueRejected()方法設置,所以在這種模式下,發生錯誤的消息是可以恢復的。
MANUAL,基本同AUTO模式,區別是需要人為調用方法給應答。
setConcurrentConsumers :設置每個MessageListenerContainer將會創建的Consumer的最小數量,默認是1個。
setMaxConcurrentConsumers :設置每個MessageListenerContainer將會創建的Consumer的最大數量,默認等於最小數量。
setPrefetchCount :設置每次請求發送給每個Consumer的消息數量。
setChannelTransacted :設置Channel的事務。
setTxSize :設置事務當中可以處理的消息數量。
setDefaultRequeueRejected :設置當rabbitmq收到nack/reject確認信息時的處理方式,設為true,扔回queue頭部,設為false,丟棄。
setErrorHandler :實現ErrorHandler介面設置進去,所有未catch的異常都會由ErrorHandler處理。
AmqpTamplate裡面有下面幾個方法可以向queue發送消息:
這里,exchange必須存在,否則消息發不出去,會看到錯誤日誌,但不影響程序運行:
Message是org.springframework.amqp.core.Message類,spring-amqp發送和接收的都是這個Message。
從Message類源碼可以看到消息內容放在byte[]裡面,MessageProperties對象包含了非常多的一些其它信息,如Header、exchange、routing key等。
這種方式,需要將消息內容(String,或其它Object)轉換為byte[],示例:
也可以直接調用下面幾個方法,Object將會自動轉為Message對象發送:
有兩種方法接收消息:
1.polling consumer,輪詢調用方法一次獲取一條;
2.asynchronous consumer,listener非同步接收消息。
polling consumer
直接通過AmqpTemplate的方法從queue獲取消息,有如下方法:
如果queue裡面沒有消息,會立刻返回null;傳入timeoutMillis參數後可阻塞等待一段時間。
如果想直接從queue獲取想要的java對象,可調用下面這一組方法:
後面4個方法是帶泛型的,示例如下:
使用這四個方法需要配置org.springframework.amqp.support.converter.SmartMessageConverter,這是一個介面,Jackson2JsonMessageConverter已經實現了這個介面,所以只要將Jackson2JsonMessageConverter設置到RabbitTemplate中即可。
asynchronous consumer
有多種方式可以實現,詳情參考官方文檔。
最簡單的實現方式是@RabbitListener註解,示例:
這里接收消息的對象用的是Message,也可以是自定義的java對象,但調用Converter轉換失敗會報錯。
註解上指定的queue必須是已經存在並且綁定到某個exchange的,否則會報錯:
如果在@RabbitListener註解中指明binding信息,就能自動創建queue、exchange並建立binding關系。
direct和topic類型的exchange需要routingKey,示例:
fanout類型的exchange,示例:
2.0版本之後,可以指定多個routingKey,示例:
並且支持arguments屬性,可用於headers類型的exchange,示例:
@Queue有兩個參數exclusive和autoDelete順便解釋一下:
exclusive,排他隊列,只對創建這個queue的Connection可見,Connection關閉queue刪除;
autoDelete,沒有consumer對這個queue消費時刪除。
對於這兩種隊列,rable=true是不起作用的。
另外,如果註解申明的queue和exchange及binding關系都已經存在,但與已存在的設置不同,比如,已存在的exchange的是direct類型,這里嘗試改為fanout類型,結果是不會有任何影響,不論是修改或者新增參數都不會生效。
如果queue存在,exchange存在,但沒有binding,那麼程序啟動後會自動建立起binding關系。
㈨ spring源碼要怎麼講
《SPRING技術內幕——深入解析SPRING架構與設計原理》
該書講了spring的ioc容器原理,在xml的spring配置文件中,對象是如何解析並生成的。
spring的aop,面向切面編程。這兩塊是比較重要的,屬於核心部分。
其他的如spring mvc ,spring jdbc與hibernate,ibatise集成,spring事務,spring security,
spring 任務調度都有介紹。
大體來說,屬於跟著代碼走向,一個類一個類介紹了一下。其實代碼都是有英文注釋的。
跟著作都的思路看過來也還是可以的,最好是對照類圖分析。
㈩ 如何評價spring源碼深度解析
您好,希望以下回答能幫助您 《SPRING技術內幕——深入解析SPRING架構與設計原理》 該書講了spring的ioc容器原理,在xml的spring配置文件中,對象是如何解析並生成的。 spring的aop,面向切面編程。這兩塊是比較重要的,屬於核心部分。 其他的如spring mvc ,spring jdbc與hibernate,ibatise集成,spring事務,spring security, spring 任務調度都有介紹。 大體來說,屬於跟著代碼走向,一個類一個類介紹了一下。其實代碼都是有英文注釋的。 跟著作都的思路看過來也還是可以的,最好是對照類圖分析。 如您還有疑問可繼續追問。