一、IOC(Inverse of Control):控制反轉,也可以稱為依賴倒置
所謂依賴,從程序的角度看,就是比如A要調用B的方法,那么A就依賴於B,因為A要用到B,所以A就必須依賴於B的方法。
所謂倒置,你必須理解如果不倒置,會怎么着,因為A必須要有B,才可以調用B,如果不倒置,意思就是A主動獲取B的實例:B b = new B(),這就是最簡單的獲取B實例的方法(當然還有各種設計模式可以幫助你去獲得B的實例,比如工廠、Locator等等),然后你就可以調用b對象了。
所以,不倒置,意味着A要主動獲取B,才能使用B;到了這里,就應該明白了倒置的意思了。倒置就是A要調用B的話,A並不需要主動獲取B,而是由其它人自動將B送上門來。
形象的舉例就是:
通常情況下,假如你有一天在家里口渴了,要喝水,那么你可以到你小區的小賣部去,告訴他們,你需要一瓶水,然后小賣部給你一瓶水!這本來沒有太大問題,關鍵是如果小賣部很遠,那么你必須知道:從你家如何到小賣部;小賣部里是否有你需要的水;你還要考慮是否開着車去;等等等等,也許有太多的問題要考慮了。
也就是說,為了一瓶水,你還可能需要依賴於車等等這些交通工具或別的工具,問題是不是變得復雜了?那么如何解決這個問題呢?
解決這個問題的方法很簡單:小賣部提供送貨上門服務,凡是小賣部的會員,你只要告知小賣部你需要什么,小賣部將主動把貨物給你送上門來!這樣一來,你只需要做兩件事情,你就可以活得更加輕松自在:
第一:向小賣部注冊為會員。
第二:告訴小賣部你需要什么。
這和Spring的做法很類似!Spring就是小賣部,你就是A對象,水就是B對象
第一:在Spring中聲明一個類:A
第二:告訴Spring,A需要B
假設A是UserAction類,而B是UserService類
<bean id="userService" class="org.leadfar.service.UserService"/>
<bean id="documentService" class="org.leadfar.service.DocumentService"/>
<bean id="orgService" class="org.leadfar.service.OrgService"/>
<bean id="userAction" class="org.leadfar.web.UserAction">
<property name="userService" ref="userService"/>
</bean>
在Spring這個商店(工廠)中,有很多對象/服務:userService,documentService,orgService,也有很多會員:userAction等等,聲明userAction需要userService即可,Spring將通過你給它提供的通道主動把userService送上門來,因此UserAction的代碼示例類似如下所示:
package org.leadfar.web; public class UserAction{ private UserService userService; public String login(){ userService.valifyUser(xxx); } public void setUserService(UserService userService){ this.userService = userService; } }
在這段代碼里面,你無需自己創建UserService對象(Spring作為背后無形的手,把UserService對象通過你定義的setUserService()方法把它主動送給了你,這就叫依賴注入!),當然咯,我們也可以使用注解來注入。
Spring依賴注入的實現技術是:動態代理。
1、IOC思想
java 程序中的每個業務邏輯至少需要兩個或以上的對象來協作完成,通常,在使用其他的合作對象時,均要使用像 new object() 這樣的語法來完成合作對象的申請工作。你會發現:對象間的耦合度高了。而 IOC 的思想是:Spring 容器來實現這些相互依賴對象的創建、協調工作。對象只需要關心業務邏輯本身就可以了。
從這方面來說,對象如何得到他的協作對象的責任被反轉了(IOC、DI)。IOC和DI是代表的含義是類似的。
2、spring的容器
在 Spring 容器啟動的時候,Spring 會把你在 application.xml 中配置好的 bean 都初始化,在你需要調用的時候,把已經初始化的 bean 分配給你要調用這些 bean 的類,而不用去創建一個對象的實例。
Ioc 的常見容器是:ApplicationContext 和 BeanFactory
3、IOC 是基於 java 的反射機制以及工廠模式實現的。
4、了解一下IOC的演進流程
非常直觀的解釋就是這一堆東西:
(1)第一時代:之前全部要一個一個 KnowledgeDAO knowledgeDAO = new KnowledgeDAO();的,
(2)第二時代:到了 spring 之后呢,就直接寫變量注入即可,但是需要寫xml文件配置或者用注解
@Autowired private final KnowledgeDAO knowledgeDAO;
(3)第三時代:到springboot之后,類上加@Service/@Controller等,對象連注解都不用寫了,直接 private final KnowledgeDAO knowledgeDAO;
當然,雖然盡管:會用簡單、概念理解簡單,但是要自己理解真正原理去實現還是有點困難的。
二、AOP:即面向切面編程
面向切面編程的目的就是分離關注點。
什么是關注點呢?就是你要做的事,就是關注點。
假如你是個公子哥,沒啥人生目標,天天就是衣來伸手,飯來張口,整天只知道玩一件事!那么,每天你一睜眼,就光想着吃完飯就去玩(你必須要做的事),但是在玩之前,你還需要穿衣服、穿鞋子、疊好被子、做飯等等等等事情,這些事情就是你的關注點,但是你只想吃飯然后玩,那么怎么辦呢?這些事情通通交給別人去干。在你走到飯桌之前,有一個專門的仆人A幫你穿衣服,仆人B幫你穿鞋子,仆人C幫你疊好被子,仆人C幫你做飯,然后你就開始吃飯、去玩(這就是你一天的正事),你干完你的正事之后,回來,然后一系列仆人又開始幫你干這個干那個,然后一天就結束了!
AOP的好處就是你只需要干你的正事,其它事情別人幫你干。
也許有一天,你想裸奔,不想穿衣服,那么你把仆人A解雇就是了!也許有一天,出門之前你還想帶點錢,那么你再雇一個仆人D專門幫你干取錢的活!這就是AOP。每個人各司其職,靈活組合,達到一種可配置的、可插拔的程序結構。
從Spring的角度看,AOP最大的用途就在於提供了事務管理的能力。
事務管理就是一個關注點,你的正事就是去訪問數據庫,而你不想管事務(太煩),所以,Spring在你訪問數據庫之前,自動幫你開啟事務,當你訪問數據庫結束之后,自動幫你提交/回滾事務!
1、分離關注點
面向切面編程的目的是分離關注點,通俗的說是指使用 aop 你可以一心關注你的正事,而其他的事交給別人處理。
AOP (面向切面編程) 技術利用一種稱為 “橫切” 的技術,解剖封裝的對象內部,並將那些影響了多個類的公共行為封裝到一個可重用模塊,這樣就能減少系統的重復代碼,降低模塊間的耦合度,並有利於未來的可操作性和可維護性。
2、橫切關注點
AOP 把軟件系統分為兩個部分:核心關注點和橫切關注點。
業務處理的主要流程是核心關注點,與之關系不大的部分是橫切關注點。橫切關注點的一個特點是,他們經常發生在核心關注點的多處,而各處都基本相似。比如權限認證、日志、事務處理。
比如提供的事務管理機制,事務管理就是一個關注點,你的正事就是去訪問數據庫(核心關注點),而你不想管事務(橫切關注點),所以,Spring 在你訪問數據庫之前,自動幫你開啟事務,當你訪問數據庫結束之后,自動幫你提交 / 回滾事務!
3、aop采用的技術
一是采用動態代理技術,利用截取消息的方式,對該消息進行裝飾,以取代原有對象行為的執行;
二是采用靜態織入的方式,引入特定的語法創建 “方面”,從而使得編譯器可以在編譯期間織入有關“方面”的代碼。這里靜態織入的原理就是在編譯期間,切面直接以字節碼形式編譯到目標字節碼中。
參考文章:https://blog.csdn.net/eson_15