生活随笔
收集整理的這篇文章主要介紹了
谈谈对 Spring 的理解
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
認識 Spring 框架
Spring 框架是 Java 應用最廣的框架,它的成功來源于理念,而不是技術本身 ,它的理念包括 IoC (Inversion of Control,控制反轉) 和 AOP(Aspect Oriented Programming,面向切面編程) 。
什么是 Spring:
Spring 是一個輕量級的 DI / IoC 和 AOP 容器的開源框架 ,來源于 Rod Johnson 在其著作**《Expert one on one J2EE design and development》**中闡述的部分理念和原型衍生而來。 Spring 提倡以**“最少侵入”**的方式來管理應用中的代碼,這意味著我們可以隨時安裝或者卸載 Spring
適用范圍:任何 Java 應用 Spring 的根本使命:簡化 Java 開發
盡管 J2EE 能夠趕上 Spring 的步伐,但 Spring 并沒有停止前進, Spring 繼續在其他領域發展,而 J2EE 則剛剛開始涉及這些領域,或者還沒有完全開始在這些領域的創新。移動開發、社交 API 集成、NoSQL 數據庫、云計算以及大數據 都是 Spring 正在涉足和創新的領域。Spring 的前景依然會很美好。
Spring 中常用術語:
框架:是能 完成一定功能 的半成品 。 框架能夠幫助我們完成的是:項目的整體框架、一些基礎功能、規定了類和對象如何創建,如何協作等 ,當我們開發一個項目時,框架幫助我們完成了一部分功能,我們自己再完成一部分,那這個項目就完成了。非侵入式設計: 從框架的角度可以理解為:無需繼承框架提供的任何類 這樣我們在更換框架時,之前寫過的代碼幾乎可以繼續使用。輕量級和重量級: 輕量級是相對于重量級而言的,輕量級一般就是非入侵性的、所依賴的東西非常少、資源占用非常少、部署簡單等等 ,其實就是比較容易使用 ,而重量級正好相反 。JavaBean: 即符合 JavaBean 規范 的 Java 類POJO:即 Plain Old Java Objects,簡單老式 Java 對象 它可以包含業務邏輯或持久化邏輯,但 不擔當任何特殊角色 且不繼承或不實現任何其它Java框架的類或接口。
注意:bean 的各種名稱——雖然 Spring 用 bean 或者 JavaBean 來表示應用組件,但并不意味著 Spring 組件必須遵循 JavaBean 規范,一個 Spring 組件可以是任意形式的 POJO。
容器: 在日常生活中容器就是一種盛放東西的器具,從程序設計角度看就是裝對象的的對象 ,因為存在放入、拿出等 操作,所以容器還要管理對象的生命周期 。
Spring 的優勢
低侵入 / 低耦合 (降低組件之間的耦合度,實現軟件各層之間的解耦)聲明式事務管理 (基于切面和慣例)方便集成其他框架 (如MyBatis、Hibernate)降低 Java 開發難度 Spring 框架中包括了 J2EE 三層的每一層的解決方案(一站式)
Spring 能幫我們做什么
①.Spring 能幫我們根據配置文件創建及組裝對象之間的依賴關系 。 ②.Spring 面向切面編程 能幫助我們無耦合的實現日志記錄,性能統計,安全控制。 ③.Spring 能非常簡單的幫我們管理數據庫事務 。 ④.Spring 還提供了與第三方數據訪問框架(如Hibernate、JPA)無縫集成 ,而且自己也提供了一套JDBC訪問模板 來方便數據庫訪問。 ⑤.Spring 還提供與第三方Web(如Struts1/2、JSF)框架無縫集成 ,而且自己也提供了一套Spring MVC 框架,來方便web層搭建。 ⑥.Spring 能方便的與Java EE(如Java Mail、任務調度)整合 ,與更多技術整合(比如緩存框架) 。
Spring 的框架結構
Data Access/Integration層 包含有JDBC、ORM、OXM、JMS和Transaction模塊。Web層 包含了Web、Web-Servlet、WebSocket、Web-Porlet模塊。AOP模塊 提供了一個符合AOP聯盟標準的面向切面編程的實現。**Core Container(核心容器):**包含有Beans、Core、Context和SpEL模塊。 Test模塊 支持使用JUnit和TestNG對Spring組件進行測試。
Spring IoC 和 DI 簡介
IoC:Inverse of Control(控制反轉)
讀作**“反轉控制”,更好理解,不是什么技術,而是一種 設計思想**,就是將原本在程序中手動創建對象的控制權,交由Spring框架來管理。 正控:若要使用某個對象,需要 自己去負責對象的創建 反控:若要使用某個對象,只需要 從 Spring 容器中獲取需要使用的對象,不關心對象的創建過程 ,也就是把創建對象的控制權反轉給了Spring框架 **好萊塢法則:**Don’t call me ,I’ll call you
一個例子
控制反轉顯然是一個抽象的概念,我們舉一個鮮明的例子來說明。
在現實生活中,人們要用到一樣東西的時候,第一反應就是去找到這件東西,比如想喝新鮮橙汁,在沒有飲品店的日子里,最直觀的做法就是:買果汁機、買橙子,然后準備開水。值得注意的是:這些都是你自己**“主動”創造**的過程,也就是說一杯橙汁需要你自己創造。
然而到了今時今日,由于飲品店的盛行,當我們想喝橙汁時,第一想法就轉換成了找到飲品店的聯系方式,通過電話等渠道描述你的需要、地址、聯系方式等,下訂單等待,過一會兒就會有人送來橙汁了。
請注意你并沒有“主動”去創造橙汁 ,橙汁是由飲品店創造的,而不是你,然而也完全達到了你的要求,甚至比你創造的要好上那么一些。
編寫第一個 Spring 程序
新建一個空的 Java 項目,命名為【spring】
新建一個名為【lib】的目錄,并添加進必要的 jar 包,導入項目
在 Packge【pojo】下新建一個【Source】類:
package pojo ; public class Source { private String fruit
; private String sugar
; private String size
;
}
在 【src】 目錄下新建一個 【applicationContext.xml】 文件,通過 xml 文件配置的方式裝配我們的 bean
< ? xml version
= "1.0" encoding
= "UTF-8" ? >
< beans xmlns
= "http://www.springframework.org/schema/beans" xmlns
: xsi
= "http://www.w3.org/2001/XMLSchema-instance" xsi
: schemaLocation
= "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" > < bean name
= "source" class = "pojo.Source" > < property name
= "fruit" value
= "橙子" / > < property name
= "sugar" value
= "多糖" / > < property name
= "size" value
= "超大杯" / > < / bean
>
< / beans
>
在 Packge【test】下新建一個【TestSpring】類:
package test ; import org. junit. Test ;
import org. springframework. context. ApplicationContext ;
import org. springframework. context. support. ClassPathXmlApplicationContext ;
import pojo. Source ; public class TestSpring { @Test public void test ( ) { ApplicationContext context
= new ClassPathXmlApplicationContext ( new String [ ] { "applicationContext.xml" } ) ; Source source
= ( Source ) context
. getBean ( "source" ) ; System . out
. println ( source
. getFruit ( ) ) ; System . out
. println ( source
. getSugar ( ) ) ; System . out
. println ( source
. getSize ( ) ) ; }
}
運行測試代碼,可以正常拿到 xml 配置的 bean
總結:
傳統的方式: 通過new 關鍵字主動創建一個對象IOC方式: 對象的生命周期由Spring來管理,直接從Spring那里去獲取一個對象。 IOC是反轉控制 (Inversion Of Control)的縮寫,就像控制權從本來在自己手里,交給了Spring。
DI:Dependency Injection(依賴注入)
指 Spring 創建對象的過程中,將對象依賴屬性(簡單值,集合,對象)通過配置設值給該對象
繼續上面的例子
在 Packge【pojo】下新建一個【JuiceMaker】類:
package pojo ; public class JuiceMaker { private Source source
= null ; public String makeJuice ( ) { String juice
= "xxx用戶點了一杯" + source
. getFruit ( ) + source
. getSugar ( ) + source
. getSize ( ) ; return juice
; }
}
在 xml 文件中配置 JuiceMaker 對象:
< ? xml version
= "1.0" encoding
= "UTF-8" ? >
< beans xmlns
= "http://www.springframework.org/schema/beans" xmlns
: xsi
= "http://www.w3.org/2001/XMLSchema-instance" xsi
: schemaLocation
= "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" > < bean name
= "source" class = "pojo.Source" > < property name
= "fruit" value
= "橙子" / > < property name
= "sugar" value
= "多糖" / > < property name
= "size" value
= "超大杯" / > < / bean
> < bean name
= "juickMaker" class = "pojo.JuiceMaker" > < property name
= "source" ref
= "source" / > < / bean
>
< / beans
>
在 【TestSpring】 中添加如下代碼:
package test ; import org. junit. Test ;
import org. springframework. context. ApplicationContext ;
import org. springframework. context. support. ClassPathXmlApplicationContext ;
import pojo. JuiceMaker ;
import pojo. Source ; public class TestSpring { @Test public void test ( ) { ApplicationContext context
= new ClassPathXmlApplicationContext ( new String [ ] { "applicationContext.xml" } ) ; Source source
= ( Source ) context
. getBean ( "source" ) ; System . out
. println ( source
. getFruit ( ) ) ; System . out
. println ( source
. getSugar ( ) ) ; System . out
. println ( source
. getSize ( ) ) ; JuiceMaker juiceMaker
= ( JuiceMaker ) context
. getBean ( "juickMaker" ) ; System . out
. println ( juiceMaker
. makeJuice ( ) ) ; }
}
運行測試代碼
總結 :IoC 和 DI 其實是同一個概念的不同角度描述,DI 相對 IoC 而言,明確描述了“被注入對象依賴 IoC 容器配置依賴對象”
IoC 如何實現的
最后我們簡單說說IoC是如何實現的。想象一下如果我們自己來實現這個依賴注入的功能,我們怎么來做? 無外乎:
讀取標注或者配置文件,看看JuiceMaker依賴的是哪個Source,拿到類名 使用反射的API,基于類名實例化對應的對象實例 將對象實例,通過構造函數或者 setter,傳遞給 JuiceMaker
我們發現其實自己來實現也不是很難,Spring實際也就是這么做的。這么看的話其實IoC就是一個工廠模式的升級版!當然要做一個成熟的IoC框架,還是非常多細致的工作要做,Spring不僅提供了一個已經成為業界標準的Java IoC框架,還提供了更多強大的功能,所以大家就別去造輪子啦!希望了解IoC更多實現細節不妨通過學習Spring的源碼來加深理解!
Spring AOP 簡介
如果說 IoC 是 Spring 的核心,那么面向切面編程就是 Spring 最為重要的功能之一了,在數據庫事務中切面編程被廣泛使用。
AOP 即 Aspect Oriented Program 面向切面編程
首先,在面向切面編程的思想里面,把功能分為核心業務功能,和周邊功能。
所謂的核心業務 ,比如登陸,增加數據,刪除數據都叫核心業務所謂的周邊功能 ,比如性能統計,日志,事務管理等等
周邊功能在 Spring 的面向切面編程AOP思想里,即被定義為切面
在面向切面編程AOP的思想里面,核心業務功能和切面功能分別獨立進行開發,然后把切面功能和核心業務功能 “編織” 在一起,這就叫AOP
AOP 的目的
AOP能夠將那些與業務無關,卻為業務模塊所共同調用的邏輯或責任(例如事務處理、日志管理、權限控制等)封裝起來 ,便于減少系統的重復代碼 ,降低模塊間的耦合度 ,并有利于未來的可拓展性和可維護性 。
AOP 當中的概念:
切入點(Pointcut) 在哪些類,哪些方法上切入(where ) 通知(Advice) 在方法執行的什么實際(**when:**方法前/方法后/方法前后)做什么(**what:**增強的功能) 切面(Aspect) 切面 = 切入點 + 通知,通俗點就是:在什么時機,什么地方,做什么增強! 織入(Weaving) 把切面加入到對象,并創建出代理對象的過程。(由 Spring 來完成)
AOP 編程
在 Packge【service】下創建 【ProductService】類:
package service ; public class ProductService { public void doSomeService ( ) { System . out
. println ( "doSomeService" ) ; }
}
在 xml 文件中裝配該 bean:
< bean name
= "productService" class = "service.ProductService" / >
在【TestSpring】中編寫測試代碼,運行
在 Packge【aspect】下準備日志切面 【LoggerAspect】類:
package aspect ; import org. aspectj. lang. ProceedingJoinPoint ; public class LoggerAspect { public Object log ( ProceedingJoinPoint joinPoint
) throws Throwable { System . out
. println ( "start log:" + joinPoint
. getSignature ( ) . getName ( ) ) ; Object object
= joinPoint
. proceed ( ) ; System . out
. println ( "end log:" + joinPoint
. getSignature ( ) . getName ( ) ) ; return object
; }
}
在 xml 文件中聲明業務對象和日志切面:
< ? xml version
= "1.0" encoding
= "UTF-8" ? >
< beans xmlns
= "http://www.springframework.org/schema/beans" xmlns
: xsi
= "http://www.w3.org/2001/XMLSchema-instance" xmlns
: aop
= "http://www.springframework.org/schema/aop" xmlns
: tx
= "http://www.springframework.org/schema/tx" xmlns
: context
= "http://www.springframework.org/schema/context" xsi
: schemaLocation
= "http
: / / www
. springframework
. org
/ schema
/ beanshttp
: / / www
. springframework
. org
/ schema
/ beans
/ spring
- beans
- 3.0 . xsdhttp
: / / www
. springframework
. org
/ schema
/ aophttp
: / / www
. springframework
. org
/ schema
/ aop
/ spring
- aop
- 3.0 . xsdhttp
: / / www
. springframework
. org
/ schema
/ txhttp
: / / www
. springframework
. org
/ schema
/ tx
/ spring
- tx
- 3.0 . xsdhttp
: / / www
. springframework
. org
/ schema
/ contexthttp
: / / www
. springframework
. org
/ schema
/ context
/ spring
- context
- 3.0 . xsd"
> < bean name
= "productService" class = "service.ProductService" / > < bean id
= "loggerAspect" class = "aspect.LoggerAspect" / > < ! -- 配置AOP
-- > < aop
: config
> < ! -- where:在哪些地方(包
. 類
. 方法)做增加
-- > < aop
: pointcut id
= "loggerCutpoint" expression
= "execution(* service.ProductService.*(..)) " / > < ! -- what
: 做什么增強
-- > < aop
: aspect id
= "logAspect" ref
= "loggerAspect" > < ! -- when
: 在什么時機(方法前
/ 后
/ 前后)
-- > < aop
: around pointcut
- ref
= "loggerCutpoint" method
= "log" / > < / aop
: aspect
> < / aop
: config
>
< / beans
>
再次運行 TestSpring 中的測試代碼,代碼并沒有改變,但是在業務方法運行之前和運行之后,都分別輸出了日志信息:
創作挑戰賽 新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔 為你收集整理的谈谈对 Spring 的理解 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。