spring工作原理
對spring原理以前寫過類似的博客,地址:點擊打開鏈接。
但是經過一些時間後,盡管天天用著spring,但一提到原理方面,就遺忘了呢?就記得AOP和IOC,但是沒有清楚的講出來呢?
思考了一下這個問題,總結例如以下。
1、對於美食的喜愛,以後學習技術的過程中,多和美食相關聯,和忘不掉的那些相關聯。
2、總是想著抓住最後一根稻草,卻從來沒有想過怎樣學會遊泳。
IOC(inversion of control)控制反轉
概念:控制權有對象本身轉向容器。由容器依據配置文件區創建實例並創建各個實例之間的依賴關系。
核心:spring封裝了抽象工廠模式;bean工廠創建的各個實例稱作為bean。
理解:喜歡吃的東西不一定自己親自去做。交給食品加工廠去做不是更好嗎。spring讓一個對象不用創建new了。能夠自己主動生產。這就是利用java的反射機制動態創建、調用對象,spring就是在執行時,根xml 是pring配置文件動態創建對象,和調用對象裏的方法的。
spring IOC 應用了單例模式,一次new一個全局對象,也能夠在配置文件裏進行配置,配置為不使用單例模式。
AOP(aspect oriented programming)面向切面編程
1、不使用代理方式
我們以這個為實例(http://blog.csdn.net/lovesummerforever/article/details/22668947),分別畫出類圖例如以下所看到的:
2、代理的兩種方式
靜態代理:
針對每一個詳細類分別編寫代理類。針對一個接口編寫一個代理類;
動態代理:
針對一個方面編程寫一個invocationHandler。然後借用JDK反射包中的proxy類為各個接口動態生成對應的代理類。
http://blog.csdn.net/lovesummerforever/article/details/22664647
怎樣使用JDK動態代理呢?
1、實現InvocationHandler接口。
2、通過Proxy,依據目標來生成代理。
3、invoke方法,該方法中調用詳細的切入方法。
動態代理與靜態代理差別
靜態代理:由程序猿創建,再對其編譯。在程序執行之前.class文件已經存在了。靜態代理:在程序執行時。運用反射的機制動態創建而完畢。無需程序猿手動編寫代碼,利用jdk的動態代理機制就可以。不僅簡化了編程工作,且提高了軟件的可擴展性,由於java的反射機制能夠生成隨意類型的動態代理。
動態代理使用場景:不同意直接訪問某些類,對訪問要做特殊處理;或者對原始方法進行統一的擴展,比如日誌的記錄。
springAOP:
springAOP核心也是動態代理,spring採用三種方式實現代理功能。
1、java的動態代理方式。2、CGlib方式。3、Aspectj方式。
默認模式
spring使用java動態代理和CGlib的混合方式提供服務。即若對象實現了接口則spring自己主動採用java動態代理進行支持。否則則採用CGlib方式進行支持;也能夠強制制定使用cglib方式代理,在配置文件裏進行配置。
(http://my.oschina.net/coldlemon/blog/178586)
比如spring aop控制事務代碼例如以下
<!--事務相關控制--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED" read-only="false" rollback-for="Exception" /> <tx:method name="delete*" propagation="REQUIRED" read-only="false" rollback-for="Exception" /> <tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="Exception" /> <tx:method name="find*" read-only="true"/> </tx:attributes> </tx:advice> <!--把事務控制在Service層--> <aop:config> <aop:pointcut id="pc" expression="execution(public * com.msc.biz.service.*.*(..))" /> <aop:advisor pointcut-ref="pc" advice-ref="txAdvice" /> </aop:config>
通過spring AOP特性來加入日誌模塊。
日誌類:
import org.apache.log4j.Logger; import org.aspectj.lang.JoinPoint; /** * 日誌記錄,加入、刪除、改動方法AOP * @author HotStrong * */ public class LogAspect { private static final Logger logger = Logger.getLogger(LogAspect.class); //在類裏面寫方法,方法名詩能夠隨意的。此處我用標準的before和after來表示 //此處的JoinPoint類能夠獲取,action全部的相關配置信息和request等內置對象。 public void before(JoinPoint joinpoint){ } public void after(JoinPoint joinpoint){ } //有參並有返回值的方法 public void logArgAndReturn(JoinPoint point, Object returnObj) { //此方法返回的是一個數組。數組中包含request以及ActionCofig等類對象 logger.debug("運行的方法名為:"+point.getSignature()); Object[] args = point.getArgs(); String arg=""; if (args != null) { for (Object obj : args) { if(obj != null){ arg+=obj.toString()+","; } } logger.debug("運行的方法參數為:"+arg); logger.debug("運行的方法返回值為:"+returnObj); } } }
配置切面,切入點,和通知
<!--針對於service中方法的監控--> <bean id="logProcess" class="com.xsc.biz.common.LogAspect"></bean> <!--將日誌類註入到bean中。--> <aop:config> <aop:aspect id="b" ref="logProcess"><!--調用日誌類--> <aop:pointcut id="log" expression="execution(* com.xsc.biz.service.*.*(..))"/><!--配置在log包下全部的類在調用之前都會被攔截--> <!--在log包以下全部的類的全部方法被調用之前都調用MyLog中的before方法--> <aop:before pointcut-ref="log" method="before"/> <!--在log包以下全部的類的全部方法被調用之後都調用MyLog中的after方法--> <aop:after pointcut-ref="log" method="after"/> <aop:after-returning method="logArgAndReturn" returning="returnObj" pointcut-ref="log"/> </aop:aspect> </aop:config>
這裏配置<aop:aspect>是針對什麽問題,調用哪個類。
<aop:pointcut>是日誌類方法的切入點,是在業務層。全部方法運行完成切入。<aop:before><aop:after>是通知什麽時候運行什麽方法<aop:after-returning>是處理結果返回時的操作。運行方法logArgAndReturn。
有些倉促。有時間一定會清晰的再整理一遍。
spring工作原理