摘 要:Spring是當(dāng)今流行的企業(yè)級(jí)應(yīng)用開發(fā)框架,它能解決大部分企業(yè)應(yīng)用開發(fā)的復(fù)雜性問題。對(duì)于Java開發(fā)人員來說,掌握Spring框架的基本使用,已是入職Java軟件開發(fā)行業(yè)的必備技能之一。本文主要介紹Spring框架及其體系結(jié)構(gòu)的基本內(nèi)容及應(yīng)用,并通過實(shí)例說明Spring框架中IoC和AOP的基本使用方法。
關(guān)鍵詞:Spring框架;IoC;AOP;企業(yè)級(jí)應(yīng)用開發(fā)
Spring的出現(xiàn)是為了更好服務(wù)于企業(yè)級(jí)應(yīng)用開發(fā)。企業(yè)級(jí)應(yīng)用是指為商業(yè)組織、大型企業(yè)創(chuàng)建并部署的解決方案及應(yīng)用。這些大型企業(yè)級(jí)應(yīng)用的結(jié)構(gòu)復(fù)雜,涉及的外部資源眾多,事務(wù)密集、數(shù)據(jù)規(guī)模大、用戶數(shù)量多,有較強(qiáng)的安全性考慮和較高的性能要求。企業(yè)級(jí)應(yīng)用絕不可能是一個(gè)個(gè)的獨(dú)立系統(tǒng)。在企業(yè)中,一般都會(huì)部署多個(gè)交互的應(yīng)用,同時(shí)這些應(yīng)用又有可能與其他企業(yè)的相關(guān)應(yīng)用連接,從而構(gòu)成一個(gè)結(jié)構(gòu)復(fù)雜的、跨越網(wǎng)絡(luò)的分布式企業(yè)應(yīng)用集群。此外,作為企業(yè)級(jí)應(yīng)用,不但要有強(qiáng)大的功能,還要能夠滿足未來業(yè)務(wù)需求的發(fā)展變化,易于擴(kuò)展和維護(hù)。而傳統(tǒng)的Java EE在解決企業(yè)級(jí)應(yīng)用問題時(shí)技術(shù)煩瑣,屬于“重量級(jí)”架構(gòu)體系,使它的開發(fā)效率、開發(fā)難度和實(shí)際性能都令人失望。而Spring作為一個(gè)新興的“輕量級(jí)”企業(yè)級(jí)應(yīng)用開發(fā)框架,致力于Java EE應(yīng)用的各種解決方案,而不僅僅專注于某一層的方案??梢哉f,Spring是企業(yè)應(yīng)用開發(fā)的最優(yōu)選擇,它貫穿表現(xiàn)層、業(yè)務(wù)層和持久層,可以和現(xiàn)有的各種技術(shù)框架無縫結(jié)合。
一、Spring整體架構(gòu)簡(jiǎn)介
Spring是一個(gè)輕量級(jí)框架,它大大簡(jiǎn)化了Java企業(yè)級(jí)開發(fā),提供強(qiáng)大、穩(wěn)定功能的同時(shí)并沒有帶來額外的負(fù)擔(dān)。它主要有兩個(gè)作用:一是讓現(xiàn)有技術(shù)更易于使用;二是養(yǎng)成良好的編程習(xí)慣。作為一個(gè)全面的解決方案,Spring堅(jiān)持一個(gè)原則:簡(jiǎn)單易用,無需重新實(shí)現(xiàn)。例如,對(duì)持久化和ORM,Spring只是對(duì)現(xiàn)有的JDBC、MyBatis、Hibernate等技術(shù)提供支持,使之更易用,而不是重新實(shí)現(xiàn)。
Spring框架由大約20個(gè)功能模塊組成。這些模塊被分為六個(gè)部分,分別是Core Container,Data Access/Integration,Web、AOP、Instrumentation及Test,如圖1所示。Spring Core是框架的最基礎(chǔ)部分,提供了IoC特性。Spring Context為企業(yè)級(jí)開發(fā)提供了便利的集成工具。Spring AOP是基于Spring Core的符合規(guī)范的面向切面編程的實(shí)現(xiàn)。Spring JDBC提供了JDBC的抽象層,簡(jiǎn)化了JDBC編碼,同時(shí)使代碼更健壯。Spring ORM對(duì)市面上流行的ORM框架提供了支持。Spring Web為Spring在Web應(yīng)用程序中的使用提供了支持。Spring IoC和AOP是Spring技術(shù)中的核心,下面介紹這兩種核心技術(shù)的情況。
二、Spring IoC核心技術(shù)介紹
控制反轉(zhuǎn)(Inversion of IoC)也稱之為依賴注入(Dependency Injection,DI),是面向?qū)ο缶幊讨械囊环N設(shè)計(jì)理念,用來降低程序代碼之間的耦合度。依賴一般指通過局部變量、方法參數(shù)、返回值等建立的對(duì)于其他對(duì)象的調(diào)用關(guān)系。例如,在A類的方法中,實(shí)例化了B類的對(duì)象并調(diào)用其方法來完成特定的功能,也就是A類依賴于B類。幾乎所有的應(yīng)用都由兩個(gè)或更多的類通過合作來實(shí)現(xiàn)完整的功能。類與類之間的依賴關(guān)系增加了程序開發(fā)的復(fù)雜程度。例如,常見的業(yè)務(wù)層調(diào)用數(shù)據(jù)訪問層以實(shí)現(xiàn)持久化操作代碼如下。
public interface UserDao{? ? ? ? ? ? ?//用戶DAO接口,定義了所需的持久化方法
public void save(User user);}
public class UserDaoImpl implements UserDao{// 用戶DAO實(shí)現(xiàn)類,實(shí)現(xiàn)User類的持久化操作
public void save(User user){
System.out.println(“保存用戶信息到數(shù)據(jù)庫(kù)”);}
public class UserServiceImpl implements UserService{//實(shí)例化所依賴的UserDao對(duì)象
private UserDao dao=new UserDaoImpl();
public void addNewUser(User user){
dao.save(user);}
如上三段代碼中,UserServiceImpl對(duì)UserDaoImpl存在依賴關(guān)系。這樣的代碼很常見,但是存在一個(gè)嚴(yán)重的問題,就是UserServiceImpl和UserDaoImpl高度耦合,如果因?yàn)樾枨笞兓枰鎿QUserDao的實(shí)現(xiàn)類,將導(dǎo)致UserServiceImpl中的代碼隨之發(fā)生修改。程序?qū)⒉痪邆鋬?yōu)良的可擴(kuò)展性和可維護(hù)性,甚至在開發(fā)中難以測(cè)試。下面我們使用IoC編程方式進(jìn)行改進(jìn)。
public class UserDaoFactory{//增加DAO工廠類,負(fù)責(zé)用戶DAO實(shí)例的創(chuàng)建工作
public static UserDao getInstance(){
......
}}
pubic class UserService Implements UserService{//通過工廠類獲取所依賴的用戶DAO對(duì)象
private UserDao dao=UserDaoFactory.getInstance();
public void addNewUser(User user){
dao.save(user);}}
上例中的用戶DAO工廠類UserDaoFactory體現(xiàn)了“控制反轉(zhuǎn)”的思想:UserServiceImpl不再依靠自身的代碼去獲得所依賴的具體DAO對(duì)象,而是把這一工作轉(zhuǎn)交給了“第三方”UserDaoFactory,從而避免了和具體UserDao實(shí)現(xiàn)類之間的耦合。由此可見,在如何獲取所依賴的對(duì)象上,“控制權(quán)”發(fā)生了“反轉(zhuǎn)”,即從UserServiceImpl轉(zhuǎn)移到了UserDaoFactory,這就是“控制反轉(zhuǎn)”IoC思想。
三、Spring AOP核心技術(shù)介紹
面向切面編程(Aspect Oriented Programming,AOP)是軟件編程思想發(fā)展到一定階段的產(chǎn)物,是對(duì)面向?qū)ο缶幊痰挠幸嫜a(bǔ)充。AOP一般適用于具有橫切邏輯的場(chǎng)合,如訪問控制、事務(wù)管理、性能檢測(cè)等。在軟件系統(tǒng)中,日志、異常處理、事務(wù)控制等都是一個(gè)健壯的業(yè)務(wù)系統(tǒng)所必需的。但為了保證系統(tǒng)的健壯性,就要在眾多的業(yè)務(wù)方法中反復(fù)編寫功能類似的代碼,使得原本就很復(fù)雜的業(yè)務(wù)處理代碼變得更加復(fù)雜。業(yè)務(wù)功能的開發(fā)者還需要關(guān)注這些額外的代碼是否處理正確,是否有遺漏。如果需要修改日志信息的格式或者安全驗(yàn)證的規(guī)則,或者再增加新的輔助功能,都會(huì)導(dǎo)致業(yè)務(wù)代碼頻繁而大量的修改。對(duì)于軟件開發(fā)人員來說,他們最希望的是無須編寫顯式的調(diào)用,在需要的時(shí)候,系統(tǒng)能夠“自動(dòng)”調(diào)用所需的功能,這正是AOP存在的必要。也就是說,面向切面編程就是在不改變?cè)谐绦虻幕A(chǔ)上通過代理對(duì)象為代碼段增加新的功能,對(duì)其進(jìn)行增強(qiáng)處理,這樣在調(diào)用原有代碼的時(shí)候會(huì)自動(dòng)執(zhí)行增加的新的功能。下面通過一個(gè)例子說明AOP編程的方法和步驟。
四、AOP實(shí)現(xiàn)思路及關(guān)鍵代碼
(1)在項(xiàng)目中添加Spring AOP相關(guān)的jar文件
(2)編寫前置增強(qiáng)和后置增強(qiáng)功能代碼
(3)編寫Spring配置文件,對(duì)業(yè)務(wù)方法進(jìn)行增強(qiáng)處理
(4)編寫測(cè)試代碼,獲取帶有增強(qiáng)處理的業(yè)務(wù)對(duì)象并運(yùn)行結(jié)果,部分關(guān)鍵代碼如下所示。
public class UserServiceLogger{//定義包含增強(qiáng)方法的JavaBean
public void before(JoinPoint jp){
.... //此處為前置增強(qiáng)代碼
}
public void afterReturning(JoinPoint jp){
.... //此處為后置增強(qiáng)代碼
}}
UserServiceLogger類中定義了before()和afterReturning()兩個(gè)方法。其中before方法作為前置增強(qiáng)使用,即將該方法添加到目標(biāo)方法之前執(zhí)行;把a(bǔ)fterReturning方法作為后置增強(qiáng)使用,即將該方法添加到目標(biāo)方法正常返回之后執(zhí)行。同時(shí)為了能夠在增強(qiáng)方法中獲得當(dāng)前連接點(diǎn)的信息,以便實(shí)施相關(guān)的判斷和處理,在增強(qiáng)方法中聲明一個(gè)JoinPoint類型的參數(shù),Spring會(huì)自動(dòng)注入實(shí)例。通過實(shí)例的getTarget方法得到被代理的目標(biāo)對(duì)象,通過getSignature方法返回被代理的目標(biāo)方法,再通過getArgs方法返回傳遞給目標(biāo)方法的參數(shù)數(shù)組。對(duì)于后置增強(qiáng)的afterReturning方法,還可以定義一個(gè)參數(shù)用于接收目標(biāo)方法的返回值。部分AOP切入點(diǎn)配置代碼如下所示。
五、結(jié)論
本文主要介紹Spring框架核心技術(shù)的基礎(chǔ)知識(shí)及一般應(yīng)用。首先講解了Spring框架的概念、作用、優(yōu)點(diǎn)、體系結(jié)構(gòu),然后介紹了Spring的兩種核心技術(shù)IoC和AOP,接下來通過實(shí)例來說明如何使用Spring框架的兩種核心技術(shù),并初步掌握Spring框架兩種核心技術(shù)的編程方法。
參考文獻(xiàn):
[1]沃爾斯. Spring實(shí)戰(zhàn) [M]. 人民郵電出版社,2016.
[2]卡內(nèi)爾. Spring開發(fā)三劍客[M],人民郵電出版社, 2020.
[3] 陳恒等. Spring Boot從入門到實(shí)戰(zhàn)[M]. 清華大學(xué)出版社,2020.
作者簡(jiǎn)介:翟高粵(1975—),男,漢族,廣西欽州人,碩士,研究方向:軟件理論、人工智能。