日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
高手組合Scala整合Spring框架

Scala近期正式發(fā)布了2.8版本,這門優(yōu)秀的編程語言將簡潔、清晰的語法與面向?qū)ο蠛秃瘮?shù)式編程范式無縫融合起來,同時又完全兼容于Java,這樣Scala就能使用Java開發(fā)者所熟知的Java API和眾多的框架了。在這種情況下,我們可以通過Scala改進并簡化現(xiàn)有的Java框架。此外,Scala的學習門檻也非常低,因為我們可以輕松將其集成到“眾所周知的Java世界中”。

成都創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設(shè),翠屏企業(yè)網(wǎng)站建設(shè),翠屏品牌網(wǎng)站建設(shè),網(wǎng)站定制,翠屏網(wǎng)站建設(shè)報價,網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,翠屏網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學習、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實用型網(wǎng)站。

推薦專題:Scala編程語言

本文將介紹如何通過Scala整合當今世界最為流行的框架之一Spring。Spring不僅支持如依賴注入和面向方面的編程等高效的編程范式,還提供了大量的膠水代碼與Hibernate、Toplink等框架以及JEE環(huán)境交互,后者更是可以保證Scala能平滑地融入到企業(yè)當中,毫無疑問,這是Spring的成功所在。

為了清楚地闡釋Scala與Spring的整合原理,本文將使用一個簡單的示例應用。這個應用會使用到Scala、Spring和Hibernate/JPA,其領(lǐng)域模型如下圖所示:

該領(lǐng)域模型展示了一個簡化的社交網(wǎng)絡(luò)應用:人與人之間可以彼此鏈接起來。

第一步

后面的講解都將基于該領(lǐng)域模型。首先介紹如何實現(xiàn)一個泛型DAO,并通過Hibernate/JPA使用Scala為Person實體實現(xiàn)一個具體的DAO,該DAO的名字為PersonDao,里面封裝了CRUD操作。如下所示:

 
 
 
 
  1. val p1 = new Person(“Rod Johnson”)   
  2. val p2 = dao.findByName(“Martin Odersky”)   
  3. p1.link(p2)  
  4. personDao.save(p1) 

第二步

接下來介紹如何將Person實體轉(zhuǎn)換為一個“內(nèi)容豐富”的領(lǐng)域?qū)ο螅谡{(diào)用link方法時,該對象內(nèi)部會使用NotificationService執(zhí)行額外的邏輯,這個服務會“神奇地”按需注入到對象中。下圖展示了這一切:

 
 
 
 
  1. val p1 = Person(“Martin Odersky”) //the omission of the ‘new’ keyword is intentional   
  2. val p2 = dao.findByName(“Rod Johnson”)   
  3. p1.link(p2) //magic happens here  
  4. personDao.save(p1)  

第三步

最后,本文將介紹Spring是如何從Scala的高級概念:特征(traits)中受益的。特征可以將內(nèi)容豐富的Person領(lǐng)域?qū)ο筠D(zhuǎn)換為羽翼豐滿的OO類,這個類能夠?qū)崿F(xiàn)所有的職責,包括CRUD操作。如下所示:

 
 
 
 
  1. Person(“Martin Odersky”).save   

第一步:使用Scala、Spring和Hibernate/JPA實現(xiàn)DAO

需求

毫無疑問,DAO在設(shè)計上應該有一個泛型DAO和一個針對Person實體的具體DAO。泛型DAO中應該包含基本的CRUD方法,如save、remove、findById和findAll等。由于是泛型,因此它處理的是類型而不是具體的實體實現(xiàn)??偟膩碚f,這個泛型DAO具有如下的接口定義:

 
 
 
 
  1. trait GenericDao[T] {  
  2.       def findAll():List[T]  
  3.       def save(entity:T):T   
  4.       def remove(entity:T):Unit  
  5.       def findById(id:Serializable):T  

Person實體類的具體DAO應該增加一個特定于Person實體的finder方法:

 
 
 
 
  1. trait PersonDao extends GenericDao[Person] {  
  2.   def findByName(name:String):List[Person]  
  3.   //more finders here…  
  4. }  

我們需要考慮如下具體的實現(xiàn)細節(jié)以便利用上Scala提供的眾多富有成效的特性:

◆關(guān)于集合:雖然底層的JPA實現(xiàn)并不知道所謂的Scala集合,但DAO接口返回的卻是Scala集合類型(scala.List)而不是Java集合。因為Scala集合要比Java集合強大的多,因此DAO方法的調(diào)用者非常希望方法能夠返回Scala集合。這樣,我們需要將JPA返回的Java集合平滑地轉(zhuǎn)換為Scala集合。

◆關(guān)于回調(diào):Spring用于粘合JPA、JMS等框架的大多數(shù)膠水代碼都是基于模板模式,比如JpaTemplate、JmsTemplate等。雖然這些模板通過一些便捷的方法在一定程度上隱藏了底層框架的復雜性,但很多時候我們還是不可避免地要直接訪問底層的實現(xiàn)類,如EntityManager、JmsSession等。在這種情況下,Spring通過JpaCallback等回調(diào)類來實現(xiàn)我們的愿望?;卣{(diào)方法doIn…(..)唯一的參數(shù)就是指向?qū)崿F(xiàn)類的引用,比如EntityManager。下面的示例闡述了這種編程模型:

 
 
 
 
  1.  
  2.  
  3. jpaTemplate.execute(new JpaCallback() {  
  4.  public Object doInJpa(EntityManager em) throws PersistenceException {  
  5.  //… do something with the EntityManager  
  6.  return null;  
  7. }  
  8. });  

上面的代碼有兩點值得我們注意:首先,匿名內(nèi)部回調(diào)類的實例化需要大量的樣板代碼。其次,還有一個限制:匿名內(nèi)部類JpaCallback之外的所有參數(shù)都必須是final的。如果從Scala的視角來看待這種回調(diào)模式,我們發(fā)現(xiàn)里面充斥的全都是某個“函數(shù)”的繁瑣實現(xiàn)。我們真正想要的只是能夠直接訪問EntityManager而已,并不需要匿名內(nèi)部類,而且還得實現(xiàn)里面的doInJpa(…)方法,這有點太小題大作了。換句話說,我們只需要下面這一行足矣:

 
 
 
 
  1.  
  2.  
  3. jpaTemplate.execute((em:EntityManager) => em.createQuery(…)// etc. );   

問題在于如何通過優(yōu)雅的方式實現(xiàn)這個功能。

◆關(guān)于getter和setter:使用了Spring bean的類至少要有一個setter方法,該方法對應于特定bean的名稱。毫無疑問,這些setter是框架所需的樣板代碼,如果不使用構(gòu)造器注入也能避免這一點豈不美哉?

實現(xiàn)

如果用Scala實現(xiàn)泛型與Person DAO,那么上面提到的一切問題都將迎刃而解,請看:

 
 
 
 
  1. object GenericJpaDaoSupport {  
  2.    
  3.    implicit def jpaCallbackWrapper[T](func:(EntityManager) => T) = {  
  4.     new JpaCallback {  
  5.       def doInJpa(session:EntityManager ) = func(session).asInstanceOf[Object]}  
  6.     }   
  7. }  
  8.  
  9. import Scala.collection.jcl.Conversions._  
  10. class GenericJpaDaoSupport[T](val entityClass:Class[T]) extends JpaDaoSupport with GenericDao[T] {  
  11.  
  12.       def findAll():List[T] = {   
  13.             getJpaTemplate().find("from " + entityClass.getName).toList.asInstanceOf[List[T]]
  14.       }  
  15.  
  16.       def save(entity:T) :T = {  
  17.         getJpaTemplate().persist(entity)  
  18.         entity  
  19.       }  
  20.  
  21.       def remove(entity:T) = {  
  22.         getJpaTemplate().remove(entity);          
  23.       }  
  24.  
  25.       def findById(id:Serializable):T = {  
  26.         getJpaTemplate().find(entityClass, id).asInstanceOf[T];  
  27.       }  
  28. }  
  29.  
  30. class JpaPersonDao extends GenericJpaDaoSupport(classOf[Person]) with PersonDao {  
  31.        
  32.         def findByName(name:String) = { getJpaTemplate().executeFind( (em:EntityManager) => {  
  33.             val query = em.createQuery("SELECT p FROM Person p WHERE p.name like :name");  
  34.             query.setParameter("name", "%" + name + "%");  
  35.             query.getResultList();  
  36.       }).asInstanceOf[List[Person]].toList  
  37.       }  
  38. }  

使用:

 
 
 
 
  1. class PersonDaoTestCase extends AbstractTransactionalDataSourceSpringContextTests {  
  2.     @BeanProperty var personDao:PersonDao = null 
  3.       
  4.     override def getConfigLocations() = Array("ctx-jpa.xml", "ctx-datasource.xml")  
  5.    
  6.     def testSavePerson {  
  7.         expect(0)(personDao.findAll().size)  
  8.         personDao.save(new Person("Rod Johnson"))  
  9.         val persons = personDao.findAll()  
  10.         expect(1)( persons size)  
  11.         assert(persons.exists(_.name ==”Rod Johnson”))  
  12.     }  

接下來解釋上面的代碼是如何解決之前遇到的那些問題的:

關(guān)于集合

Scala 2.7.x提供了一個方便的Java集合到Scala集合的轉(zhuǎn)換類,這是通過隱式轉(zhuǎn)換實現(xiàn)的。上面的示例將一個Java list轉(zhuǎn)換為Scala list,如下代碼所示:

導入Scala.collection.jcl.Conversions類的所有方法:

 
 
 
 
  1. import Scala.collection.jcl.Conversions._  

這個類提供了隱式的轉(zhuǎn)換方法將Java集合轉(zhuǎn)換為對應的Scala集合“包裝器”。對于java.util.List來說,Scala會創(chuàng)建一個Scala.collection.jcl.BufferWrapper。

調(diào)用BufferWrapper的toList()方法返回Scala.List集合的一個實例。

下面的代碼闡述了這個轉(zhuǎn)換過程:

 
 
 
 
  1. def findAll() : List[T]  = {   
  2.     getJpaTemplate().find("from " + entityClass.getName).toList.asInstanceOf[List[T]]

總是手工調(diào)用“toList”方法來轉(zhuǎn)換集合有些麻煩。幸好,Scala 2.8(在本文撰寫之際尚未發(fā)布最終版)將會解決這個瑕疵,它可以通過scala.collection.JavaConversions類將Java轉(zhuǎn)換為Scala,整個過程完全透明。

關(guān)于回調(diào)

可以通過隱式轉(zhuǎn)換將Spring回調(diào)輕松轉(zhuǎn)換為Scala函數(shù),如GenericJpaDaoSupport對象中所示:

 
 
 
 
  1.  
  2.  
  3. implicit def jpaCallbackWrapper[T](func:(EntityManager) => T) = {  
  4.     new JpaCallback {  
  5. def doInJpa(session:EntityManager ) = func(session).asInstanceOf[Object]}  
  6. }  

借助于這個轉(zhuǎn)換,我們可以通過一個函數(shù)來調(diào)用JpaTemplate的execute方法而無需匿名內(nèi)部類JPACallback了,這樣就能直接與感興趣的對象打交道了:

 
 
 
 
  1. jpaTemplate.execute((em:EntityManager) => em.createQuery(…)// etc. ); 

這么做消除了另一處樣板代碼。

關(guān)于getter和setter

默認情況下,Scala編譯器并不會生成符合JavaBean約定的getter和setter方法。然而,可以通過在實例變量上使用Scala注解來生成JavaBean風格的getter和setter方法。下面的示例取自上文的PersonDaoTestCase:

 
 
 
 
  1. import reflect._  
  2. @BeanProperty var personDao:PersonDao = _ 

@BeanProperty注解告訴Scala編譯器生成setPersonDao(…)和getPersonDao()方法,而這正是Spring進行依賴注入所需的。這個簡單的想法能為每個實例變量省掉3~6行的setter與getter方法代碼。

第二步:按需進行依賴注入的富領(lǐng)域?qū)ο?/strong>

到目前為止,我們精簡了DAO模式的實現(xiàn),該實現(xiàn)只能持久化實體的狀態(tài)。實體本身并沒有什么,它只維護了一個狀態(tài)而已。對于領(lǐng)域驅(qū)動設(shè)計(DDD)的擁躉來說,這種簡單的實體并不足以應對復雜領(lǐng)域的挑戰(zhàn)。一個實體若想成為富領(lǐng)域?qū)ο蟛粌H要包含狀態(tài),還得能調(diào)用業(yè)務服務。為了達成這一目標,需要一種透明的機制將服務注入到領(lǐng)域?qū)ο笾?,不管對象在何處實例化都該如此?/p>

Scala與Spring的整合可以在運行期輕松將服務透明地注入到各種對象中。后面將會提到,這種機制的技術(shù)基礎(chǔ)是DDD,可以用一種優(yōu)雅的方式將實體提升為富領(lǐng)域?qū)ο蟆?/p>

需求

為了說清楚何謂按需的依賴注入,我們?yōu)檫@個示例應用加一個新需求:在調(diào)用Person實體的link方法時,它不僅會鏈接相應的Person,還會調(diào)用NotificationService以通知鏈接的雙方。下面的代碼闡述了這個新需求:

 
 
 
 
  1. class Person   
  2. {     @BeanProperty var notificationService:NotificationService = _    def link(relation:Person) =   
  3. {       relations.add(relation)       notificationService.nofity(PersonLinkageNotification(this, relation))      
  4. }     //other code omitted for readability   
  5.   }    

毫無疑問,在實例化完P(guān)erson實體或從數(shù)據(jù)庫中取出Person實體后就應該可以使用NotificationService了,無需手工設(shè)置。

使用Spring實現(xiàn)自動裝配  

我們使用Spring的自動裝配來實現(xiàn)這個功能,這是通過Java單例類RichDomainObjectFactory達成的:

 
 
 
 
  1.  public class RichDomainObjectFactory implements BeanFactoryAware   
  2. {         
  3. pritic RichDomainObjectFactory singleton = new   
  4. RichDomainObjectFactory();              
  5. public static RichDomainObjectFactory autoWireFactory()   
  6. {           
  7.  return singleton;        
  8. }   
  9. public void autowire(Object instance)   
  10. {            
  11. factory.autowireBeanProperties(instance)  
  12. }         
  13. public void setBeanFactory(BeanFactory factory) throws BeansException {            
  14. this.factory = (AutowireCapableBeanFactory) factory;       
  15.  }         
  16.  }   

通過將RichDomainObjectFactory聲明為Spring bean,Spring容器確保在容器初始化完畢后就設(shè)定好了AutowireCapableBeanFactory:

 
 
 
 
  1.  

這里并沒有讓Spring容器創(chuàng)建自己的RichDomainObjectFactory實例,而是在bean定義中使用了factory-method屬性,它會強制Spring使用autoWireFactory()方法返回的引用,該引用是單例的。這樣會將AutowireCapableBeanFactory注入到單例的RichDomainObjectFactory中。由于可以在同一個類裝載器范圍內(nèi)訪問單例對象,這樣該范圍內(nèi)的所有類都可以使用RichDomainObjectFactory了,它能以一種非侵入、松耦合的方式使用Spring的自動裝配特性。毋庸置疑,Scala代碼也可以訪問到RichDomainObjectFactory單例并使用其自動裝配功能。

在設(shè)定完這個自動裝配工廠后,接下來需要在代碼/框架中定義鉤子(hook)了。總的來說需要在兩個地方定義:

◆ORM層,它負責從數(shù)據(jù)庫中加載實體

◆需要“手工”創(chuàng)建新實體的代碼中

自動裝配ORM層中的領(lǐng)域?qū)ο?/strong>

由于文中的示例代碼使用了JPA/Hibernate,因此在實體加載后需要將這些框架所提供的設(shè)備掛載到RichDomainObjectFactory中。JPA/Hibernate提供了一個攔截器API,這樣可以攔截和定制實體加載等事件。為了自動裝配剛加載的實體,需要使用如下的攔截器實現(xiàn):

 
 
 
 
  1. class DependencyInjectionInterceptor extends EmptyInterceptor {  
  2.     override def onLoad(instance:Object, id:Serializable, propertieValues:Array[Object],propertyNames:Array[String], propertyTypes:Array[Type]) = {  
  3.       RichDomainObjectFactory.autoWireFactory.autowire(instance)  
  4.       false  
  5.    }  

該攔截器需要做的唯一一件事就是將加載的實體傳遞給RichDomainObjectFactory的autowire方法。對于該示例應用來說,onLoad方法的實現(xiàn)保證了每次從數(shù)據(jù)庫中加載Person實體后都將NotificationService注入其中。

此外,還需要通過hibernate.ejb.interceptor屬性將攔截器注冊到JPA的持久性上下文中:

 
 
 
 
  1.  
  2.      org.hibernate.ejb.HibernatePersistence 
  3.         
  4.       
  5.       
  6.  

DependencyInjectionInterceptor非常強大,每次從數(shù)據(jù)庫中加載實體后它都能將在Spring中配置的服務注入其中。那如果我們在應用代碼而非JAP等框架中實例化實體時又該怎么辦呢?

自動裝配“手工”實例化的領(lǐng)域?qū)ο?/p>

要想自動裝配應用代碼中實例化的實體,最簡單也是最笨的辦法就是通過RichDomainObjectFactory的方式顯式進行自動裝配。由于這個辦法將RichDomainObjectFactory類與實體創(chuàng)建代碼緊耦合起來,因此并不推薦使用。幸好,Scala提供了“組件對象”的概念,它擔負起工廠的職責,可以靈活實現(xiàn)構(gòu)造邏輯。

對于該示例應用,我們采用如下方式實現(xiàn)Person對象以便“自動”提供自動裝配功能:

 
 
 
 
  1. import org.jsi.di.spring.RichDomainObjectFactory._  
  2. object Person {  
  3.     def apply(name:String) = {  
  4.        autoWireFactory.autowire(new Person(name))  
  5.     }  

import聲明會導入RichDomainObjectFactory的所有靜態(tài)方法,其中的autoWireFactory()方法會處理RichDomainObjectFactory單例對象。

Scala對象另一個便利的構(gòu)造手段就是apply()方法,其規(guī)則是擁有apply方法的任何對象在調(diào)用時可以省略掉.apply()。這樣,Scala會將對Person()的調(diào)用轉(zhuǎn)給Person.apply(),因此可以將自動裝配代碼放到apply()方法中。

這樣,無需使用“new”關(guān)鍵字就可以調(diào)用Person()了,它會返回一個新的實體,返回前所有必要的服務都已經(jīng)注入進去了,該實體也成為一個“富”DDD實體了。

現(xiàn)在我們可以使用富領(lǐng)域?qū)ο罅?,它是可持久化的,也能在需要時調(diào)用其中的服務:

 
 
 
 
  1. trait JpaPersistable[T] extends JpaDaoSupport  {  
  2.    def getEntity:T;  
  3.  
  4.    def findAll():List[T] = {   
  5.         getJpaTemplate().find("from " + getEntityClass.getName).toList.asInstanceOf[List[T]]  
  6.    }  
  7.  
  8.    def save():T = {  
  9.        getJpaTemplate().persist(getEntity)  
  10.        getEntity  
  11.    }  
  12.  
  13.    def remove() = {  
  14.        getJpaTemplate().remove(getEntity);          
  15.    }  
  16.         
  17.    def findById(id:Serializable):T = {  
  18.         getJpaTemplate().find(getEntityClass, id).asInstanceOf[T];  
  19.    }  
  20.    //…more code omitted for readability        
  21. }  

在繼續(xù)之前,我們需要解釋一下為何要用Java而不是Scala來實現(xiàn)RichDomainObjectFactory,原因是由Scala處理static的方式造成的。Scala故意沒有提供static關(guān)鍵字,因為static與復合的OO/函數(shù)式范式有沖突。Scala語言所提供的唯一一個靜態(tài)特性就是對象,其在Java中的等價物就是單例。由于Scala缺少static方法,因此Spring沒法通過上文介紹的factory-method屬性獲得RichDomainObjectFactory這樣的工廠對象。這樣,我們就沒法將Spring的AutowireCapableBeanFactory直接注入到Person對象中了。因此,這里使用Java而非Scala來利用Spring的自動裝配功能,它能徹底填充static鴻溝。

第三步:使用Scala traits打造功能完善的領(lǐng)域?qū)ο?/strong>

到目前為止一切尚好,此外,Scala還為OO純粹主義者提供了更多特性。使用DAO持久化實體與純粹的OO理念有些許沖突。從廣泛使用的DAO/Repository模式的角度來說,DAO只負責執(zhí)行持久化操作,而實體則只維護其狀態(tài)。但純粹的OO對象不僅有狀態(tài),還要有行為。

上文介紹的實體是擁有服務的,這些服務封裝了一些行為性職責,但持久化部分并不在其中。為什么不把所有的行為性和狀態(tài)性職責都賦給實體呢,就像OO純粹主義者所倡導的那樣,讓實體自己負責持久化操作。事實上,這是習慣問題。但使用Java很難以優(yōu)雅的方式讓實體自己去實現(xiàn)持久化操作。這種設(shè)計嚴重依賴于繼承,因為持久化方法要在父類中實現(xiàn)。這種方式相當麻煩,也缺少靈活性。Java從概念上就缺少一個良好設(shè)計的根基,沒法很好地實現(xiàn)這種邏輯。但Scala則不同,因為Scala有traits。

所謂trait就是可以包含實現(xiàn)的接口。它類似于C++中多繼承的概念,但卻沒有眾所周知的diamond syndrome副作用。通過將DAO代碼封裝到trait中,該DAO trait所提供的所有持久化方法可自動為所有實現(xiàn)類所用。這種方式完美地詮釋了DRY(Don’t Repeat Yourself)準則,因為持久化邏輯只實現(xiàn)一次,在需要的時候可以多次混合到領(lǐng)域類中。

對于該示例應用來說,其DAO trait如下代碼所示:

 
 
 
 
  1. trait JpaPersistable[T] extends JpaDaoSupport  {  
  2.    def getEntity:T;  
  3.  
  4.    def findAll():List[T] = {   
  5.         getJpaTemplate().find("from " + getEntityClass.getName).toList.asInstanceOf[List[T]]  
  6.    }  
  7.  
  8.    def save():T = {  
  9.        getJpaTemplate().persist(getEntity)  
  10.        getEntity  
  11.    }  
  12.  
  13.    def remove() = {  
  14.        getJpaTemplate().remove(getEntity);          
  15.    }  
  16.         
  17.    def findById(id:Serializable):T = {  
  18.         getJpaTemplate().find(getEntityClass, id).asInstanceOf[T];  
  19.    }  
  20.    //…more code omitted for readability        
  21. }  

作為一個傳統(tǒng)的DAO,該trait繼承了Spring的JpaDaoSupport,但它并沒有提供save、update和delete方法(這些方法需要接收一個實體作為參數(shù))轉(zhuǎn)而定義了一個抽象方法getEntity,需要持久化功能的領(lǐng)域?qū)ο蟮脤崿F(xiàn)這個方法。JpaPersistable trait在內(nèi)部實現(xiàn)中使用getEntity來保存、更新和刪除特定的實體,如下代碼片段所示。

 
 
 
 
  1. trait JpaPersistable[T] extends JpaDaoSupport  {  
  2. def getEntity:T  
  3.         
  4. def remove() = {  
  5.    getJpaTemplate().remove(getEntity);          
  6. }  
  7. //…more code omitted for readability  

實現(xiàn)該trait的領(lǐng)域?qū)ο笾恍鑼崿F(xiàn)getEntity方法即可,該方法的實現(xiàn)僅僅是返回一個自身引用:

 
 
 
 
  1. class Person extends JpaPersistable[Person] with java.io.Serializable {  
  2.  
  3.   def getEntity = this 
  4.   //…more code omitted for readability  
  5. }  

這就是全部了。所有需要持久化行為的領(lǐng)域?qū)ο笾恍鑼崿F(xiàn)JpaPersistable trait即可。最后我們得到的是一個包含了狀態(tài)和行為功能完善的領(lǐng)域?qū)ο?,完全符合純粹的OO編程的理念:

 
 
 
 
  1. Person(“Martin Odersky”).save  

無論你是否為純粹的OO理念的擁護者,這個示例都闡釋了Scala(尤其是traits概念)是如何輕松實現(xiàn)純粹的OO設(shè)計的。

結(jié)論

本文示例介紹了Scala與Spring是如何實現(xiàn)互補的。Scala簡明、強大的范式(比如函數(shù)與特征)再結(jié)合Spring的依賴注入、AOP和Java AP為我們I提供了更廣闊的空間,相對于Java代碼來說,Scala的實現(xiàn)更具表現(xiàn)力、代碼量也更少。
如果具有Spring和Java基礎(chǔ),Scala的學習曲線非常低,因為我們只需要學習一門新語言就行,無需再學大量的API了。

Scala和Spring所提供的眾多功能使得這一組合成為企業(yè)采用Scala的最佳選擇??傊覀兡芤詷O低的代價遷移到更加強大的編程范式上來。

關(guān)于作者

Urs Peter是Xebia的高級咨詢師,專注于企業(yè)級Java和敏捷開發(fā)。它有9年的IT從業(yè)經(jīng)歷。在整個IT職業(yè)生涯中,他擔任過不同角色,從開發(fā)者、軟件架構(gòu)師到Scrum Master。目前,他在下一代的荷蘭鐵路信息系統(tǒng)項目中擔任Scrum Master,該項目部分使用Scala實現(xiàn)。他還是Xebia的一名Scala布道師和荷蘭Scala用戶組的活躍分子。

文中所用源代碼

感興趣的讀者可以使用git:git clone git://github.com/upeter/Scala-Spring-Integration.git在http://github.com/upeter/Scala-Spring-Integration上下載完整的源代碼并使用maven構(gòu)建。

查看英文原文:Scala & Spring: Combine the best of both worlds

【編輯推薦】

  1. 編程思想碰撞 Scala不是改良的Java
  2. Scala 2.8最終發(fā)布 全新功能值得期待
  3. Scala vs F#:函數(shù)式編程特性大比拼(一)
  4. Scala vs F#:函數(shù)式編程特性大比拼(二)
  5. 用Java在各種框架下編譯Scala項目

網(wǎng)站題目:高手組合Scala整合Spring框架
當前路徑:http://m.5511xx.com/article/cdpgieh.html