黑馬程序員spring知識總結 技術帖.docx_第1頁
黑馬程序員spring知識總結 技術帖.docx_第2頁
黑馬程序員spring知識總結 技術帖.docx_第3頁
黑馬程序員spring知識總結 技術帖.docx_第4頁
黑馬程序員spring知識總結 技術帖.docx_第5頁
已閱讀5頁,還剩60頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

Spring框架一、技術說明(技術介紹,技術優(yōu)勢以及發(fā)展史等)1.1、什么是springl Spring是分層的JavaSE/EE full-stack 輕量級開源框架分層:三層體系結構,為每一個層都提供解決方案web層:struts2、spring-mvcservice層:springdao層:hibernate、mybatis、jdbcTemplate(spring)輕量級:使用時占用資源少,依賴程序少。比較:EJB1.2、spring由來Expert One-to-One J2EE Design and Development ,介紹EJB,使用,特點Expert One-to-One J2EE Development without EJB ,不使用EJB,spring思想1.3、spring核心l 以IoC(Inverse of Control 反轉控制)和AOP(Aspect Oriented Programming 面向切面編程為內(nèi)核)1.4、spring優(yōu)點l 方便解耦,簡化開發(fā) (易擴展,易維護) Spring就是一個大工廠,可以將所有對象創(chuàng)建和依賴關系維護,交給Spring管理l AOP編程的支持 Spring提供面向切面編程,可以方便的實現(xiàn)對程序進行權限攔截、運行監(jiān)控等功能l 聲明式事務的支持 只需要通過配置就可以完成對事務的管理,而無需手動編程l 方便程序的測試 Spring對Junit4支持,可以通過注解方便的測試Spring程序l 方便集成各種優(yōu)秀框架 Spring不排斥各種優(yōu)秀的開源框架,其內(nèi)部提供了對各種優(yōu)秀框架(如:Struts、Hibernate、MyBatis、Quartz等)的直接支持l 降低JavaEE API的使用難度 Spring 對JavaEE開發(fā)中非常難用的一些API(JDBC、JavaMail、遠程調(diào)用等),都提供了封裝,使這些API應用難度大大降低1.5、spring體系結構l spring 核心功能:beans、core、context、expression二、環(huán)境搭建(技術開發(fā)環(huán)境)2.1、獲取 Spring framework jar 包 1、spring官網(wǎng)下載從官網(wǎng)下載spring 最新的相關jar包,官網(wǎng)download地址 /springcommunity-download 下載完成后會發(fā)現(xiàn)三個目錄,命名很明確。 Docs 目錄相關文檔。包括一份 API 和一份各種 spring 的使用說明(reference),reference 提供了 HTML.PDF 版本,非常詳細。 2.spring包的核心包 搭建第一個用到 spring 依賴注冊的程序 直接用 eclipse 建立一個 JAVA 項目 然后添加 spring 的 jar 包引入 spring-core-3.2.0.M1.jar 核心依賴 jar 包 spring-context-3.2.0.M1.jar Spring 容器包 spring-beans-3.2.0.M1.jar Spring beans 的管理包 spring-asm-3.2.0.M1.jar Spring 注:和 hibernate 一起用時這個 JAR 會沖突,解決方法刪掉它就是了 org.springframework.beans.factory.BeanCreationException: Error creating bean with name sessionFactory defined in ServletContext resource /WEB-INF/classes/applicationContext.xml: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: org.objectweb.asm.ClassVisitor.visit(IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;) Caused by: java.lang.NoSuchMethodError: org.objectweb.asm.ClassVisitor.visit(IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)spring-expression-3.2.0.M1.jar 除此之外,還有需要一個 Apache common 的 JAR 包 注:如果忘記添加會 commons-logging-1.1.1.jar 報錯Exception in thread main java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory commons-logging-1.1.1.jar 日志記錄 3. 配置 XML Spring 的最大的作用就是提供 bean 的管理功能,在 spring 中 bean 的管理是通過 XML 實現(xiàn)的,要 用此功能,需要把 bean 配置到 spring 的 xml 1. 新建立一個 xml.名字任意,如 applicationContext.xml,或者 text.xml 都可以 2. 添加 xml 頭定義 Xmlns(XML NameSpace) 聲明命名空間,建議是用網(wǎng)址做命名空間,但并不會去訪問改網(wǎng)址, 僅僅是 namespace 和 xsd(xsd 是 spring 這個 xml 的 schema 文件,里面定義配置內(nèi)容)里 聲明的 targetNamespace 保持一致 . 注:這里命名空間是改不了的,其實是在代碼中也寫死了,可以打開 spring-beans3.2.0.M1-sources.jar 包的 orgspringframeworkbeansfactoryxmlBeanDefinitionParserDelegate.java 查看對 /schema/beans這個namespace的定義。 schemaLoacation .用于綁定命名空間的 schema 文件,通常是用 URL 值對,中間用空格隔 開,前面 URL 是命名空間,后面 URL 為 schema 的文件地址 xsd 的存放地址,如果沒有聲明,eclipse 會去網(wǎng)上下載. 在創(chuàng)建 xml 時,在 eclipse 編輯 xml 配置沒有提示。 可以對 eclipse 中進行 schema 文件的添加 具體是 WindowsPreferences ,搜索 XML catalog,添加 schema 文件。 Spring 的 schema 文件在下載包里有,找到 spring-3.2.0.M1schemabeansspring-beans-3.2.xsd 然后添加,編寫 spring 配置文件就能有提示了 4. 依賴注入 4.1 、spring注入的簡單案例(入門級)新建一個 class 用于注入, package org.beans; public class Test public void say() System.out.println(welcome); 把類通過 xml 配置注入 測試:package org.beans; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class testBeans public static void main(String args) ApplicationContext ctx = new ClassPathXmlApplicationContext(test.xml); Test test=(Test) ctx.getBean(test); test.say(); 4.2、spring框架為我們提供了三種注入方式,分別是set注入,構造方法注入,接口注入。接口注入不作要求,下面介紹前兩種方式。1、set注入 采用屬性的set方法進行初始化,就成為set注入。 1)給普通字符類型賦值。javaview plaincopyprint?1. publicclassUser2. privateStringusername;3. 4. publicStringgetUsername()5. returnusername;6. 7. publicvoidsetUsername(Stringusername)8. this.username=username;9. 10. 我們只需要提供屬性的set方法,然后去屬性文件中去配置好讓框架能夠找到applicationContext.xml文件的beans標簽。標簽beans中添加bean標簽,指定id,class值,id值不做要求,class值為對象所在的完整路徑。bean標簽再添加property 標簽,要求,name值與User類中對應的屬性名稱一致。value值就是我們要給User類中的username屬性賦的值。1. 2. 3. 2)給對象賦值同樣提供對象的set方法1. publicclassUser2. privateUserServiceuserservice;3. publicUserServicegetUserservice()4. returnuser;5. 6. publicvoidsetUserservice(UserServiceuserservice)7. this.userservice=userservice;8. 9. 配置文件中要增加UserService的bean標簽聲明及User對象對UserService引用。1. 2. 3. 4. 5. 6. 這樣配置,框架就會將UserService對象注入到User類中。 3)給list集合賦值同樣提供set方法1. publicclassUser2. privateListusername;3. publicListgetUsername()4. returnusername;5. 6. publicvoidsetUsername(Listusername)7. this.username=username;8. 9. 1. 2. 3. 4. zhang,san5. lisi6. wangwu7. 8. 9. 4)給屬性文件中的字段賦值1. publicclassUser2. privatePropertiesprops;3. publicPropertiesgetProps()4. returnprops;5. 6. publicvoidsetProps(Propertiesprops)7. ps=props;8. 9. 1. 2. 3. 4. jdbc:oracle:thin:localhost:orl5. oracle.jdbc.driver.OracleDriver6. scott7. tiger8. 9. 10. 標簽中的key值是.properties屬性文件中的名稱注意: 無論給什么賦值,配置文件中標簽的name屬性值一定是和對象中名稱一致。2、構造方法注入 1)構造方法一個參數(shù)1. publicclassUser2. privateStringusercode;3. publicUser(Stringusercode)4. this.usercode=usercode;5. 6. 1. 2. 3. 2)構造函數(shù)有兩個參數(shù)時 當參數(shù)為非字符串類型時,在配置文件中需要制定類型,如果不指定類型一律按照字符串類型賦值。 當參數(shù)類型不一致時,框架是按照字符串的類型進行查找的,因此需要在配置文件中制定是參數(shù)的位置1. 2. 3. 這樣制定,就是構造函數(shù)中,第一個參數(shù)為string類型,第二個參數(shù)為int類型5、Spring的junit單元測試單元測試以set注入的第一個實例為測試對象。進行單元測試。1,拷貝jar包junit-3.8.2.jar(4.x主要增加注解應用)2,寫業(yè)務類1. publicclassUser2. privateStringusername;3. 4. publicStringgetUsername()5. returnusername;6. 7. publicvoidsetUsername(Stringusername)8. this.username=username;9. 10. 11. /添加方法12. publicStringlogin()throwsException13. if(admin.equals(username)14. returnsuccess;15. else16. returnerror;17. 18. 19. 3,定義測試類 測試類最好單獨建立項目,或者單獨定義文件夾存儲,需要繼承junit.framework.TestCase4,增加測試方法測試方法必須是public,不應該有返回值,方法名必須以test開頭,無參數(shù)測試方法是有執(zhí)行先后順序,按照方法的定義先后順序多個測試方法對同一個業(yè)務方法進行測試,一般每個邏輯分支結構都有測試到。1. publicclassTestUserextendsTestCase2. publicvoidtestUser_Success()throwsException3. /準備數(shù)據(jù)4. Useraction=newUser();5. action.setUsername(admin);6. 7. /調(diào)用被測試方法8. Stringresult=action.login();9. 10. /判斷測試是否通過11. assertEquals(success,result);12. 13. 運行程序,如果測試成功會出現(xiàn)如下圖所示的結果如果運行失敗,有方法沒有通過測試,那么就會顯示出在哪個方法出錯了。上圖中綠色的條會變成紅色的。5,測試類的生命周期方法1. 2. /用來進行初始化操作3. Override4. protectedvoidsetUp()throwsException5. System.out.println(setUp.);6. 7. 8. /用來做銷毀操作9. Override10. protectedvoidtearDown()throwsException11. System.out.println(tearDown.);12. setUp方法會在每一個測試方法前執(zhí)行一次。tearDown方法會在每一個測試方法后執(zhí)行一次6、Spring對注解(Annotation)處理源碼分析1掃描和讀取Bean定義1、SpringIoC容器對于類級別的注解和類內(nèi)部的注解分以下兩種處理策略:(1).類級別的注解:如Component、Repository、Controller、Service以及JavaEE6的ManagedBean和Named注解,都是添加在類上面的類級別注解,Spring容器根據(jù)注解的過濾規(guī)則掃描讀取注解Bean定義類,并將其注冊到Spring IoC容器中。(2).類內(nèi)部的注解:如Autowire、Value、Resource以及EJB和WebService相關的注解等,都是添加在類內(nèi)部的字段或者方法上的類內(nèi)部注解,SpringIoC容器通過Bean后置注解處理器解析Bean內(nèi)部的注解。下面將根據(jù)這兩種處理策略,分別分析Spring處理注解相關的源碼。2.AnnotationConfigApplicationContext對注解Bean初始化:Spring中,管理注解Bean定義的容器有兩個:AnnotationConfigApplicationContext和AnnotationConfigWebApplicationContex。這兩個類是專門處理Spring注解方式配置的容器,直接依賴于注解作為容器配置信息來源的IoC容器。AnnotationConfigWebApplicationContext是AnnotationConfigApplicationContext的web版本,兩者的用法以及對注解的處理方式幾乎沒有什么差別,因此本文將以AnnotationConfigApplicationContext為例進行講解。AnnotationConfigApplicationContext的源碼如下:1. publicclassAnnotationConfigApplicationContextextendsGenericApplicationContext2. /創(chuàng)建一個讀取注解的Bean定義讀取器,并將其設置到容器中3. privatefinalAnnotatedBeanDefinitionReaderreader=newAnnotatedBeanDefinitionReader(this);4. /創(chuàng)建一個掃描指定類路徑中注解Bean定義的掃描器,并將其設置到容器中5. privatefinalClassPathBeanDefinitionScannerscanner=newClassPathBeanDefinitionScanner(this);6. /默認構造函數(shù),初始化一個空容器,容器不包含任何Bean信息,需要在稍后通過調(diào)用其register()/方法注冊配置類,并調(diào)用refresh()方法刷新容器,觸發(fā)容器對注解Bean的載入、解析和注冊過程7. publicAnnotationConfigApplicationContext()8. 9. /最常用的構造函數(shù),通過將涉及到的配置類傳遞給該構造函數(shù),以實現(xiàn)將相應配置類中的Bean10. /自動注冊到容器中11. publicAnnotationConfigApplicationContext(Class.annotatedClasses)12. register(annotatedClasses);13. refresh();14. 15. /該構造函數(shù)會自動掃描以給定的包及其子包下的所有類,并自動識別所有的SpringBean,將其16. /注冊到容器中17. publicAnnotationConfigApplicationContext(String.basePackages)18. scan(basePackages);19. refresh();20. 21. /為容器的注解Bean讀取器和注解Bean掃描器設置Bean名稱產(chǎn)生器22. publicvoidsetBeanNameGenerator(BeanNameGeneratorbeanNameGenerator)23. this.reader.setBeanNameGenerator(beanNameGenerator);24. this.scanner.setBeanNameGenerator(beanNameGenerator);25. 26. /為容器的注解Bean讀取器和注解Bean掃描器設置作用范圍元信息解析器27. publicvoidsetScopeMetadataResolver(ScopeMetadataResolverscopeMetadataResolver)28. this.reader.setScopeMetadataResolver(scopeMetadataResolver);29. this.scanner.setScopeMetadataResolver(scopeMetadataResolver);30. 31. /為容器注冊一個要被處理的注解Bean,新注冊的Bean,必須手動調(diào)用容器的32. /refresh()方法刷新容器,觸發(fā)容器對新注冊的Bean的處理33. publicvoidregister(Class.annotatedClasses)34. this.reader.register(annotatedClasses);35. 36. /掃描指定包路徑及其子包下的注解類,為了使新添加的類被處理,必須手動調(diào)用37. /refresh()方法刷新容器38. publicvoidscan(String.basePackages)39. this.scanner.scan(basePackages);40. 41. 通過對AnnotationConfigApplicationContext的源碼分析,我們了解到Spring對注解的處理分為兩種方式:(1).直接將注解Bean注冊到容器中:可以在初始化容器時注冊;也可以在容器創(chuàng)建之后手動調(diào)用注冊方法向容器注冊,然后通過手動刷新容器,使得容器對注冊的注解Bean進行處理。(2).通過掃描指定的包及其子包下的所有類:在初始化注解容器時指定要自動掃描的路徑,如果容器創(chuàng)建以后向給定路徑動態(tài)添加了注解Bean,則需要手動調(diào)用容器掃描的方法,然后手動刷新容器,使得容器對所注冊的Bean進行處理。接下來,將會對兩種處理方式詳細分析其實現(xiàn)過程。3.AnnotationConfigApplicationContext注冊注解Bean:當創(chuàng)建注解處理容器時,如果傳入的初始參數(shù)是具體的注解Bean定義類時,注解容器讀取并注冊。(1).AnnotationConfigApplicationContext通過調(diào)用注解Bean定義讀取器AnnotatedBeanDefinitionReader的register方法向容器注冊指定的注解Bean注解Bean定義讀取器向容器注冊注解Bean的源碼如下:1. /注冊多個注解Bean定義類2. publicvoidregister(Class.annotatedClasses)3. for(ClassannotatedClass:annotatedClasses)4. registerBean(annotatedClass);5. 6. 7. /注冊一個注解Bean定義類8. publicvoidregisterBean(ClassannotatedClass)9. registerBean(annotatedClass,null,(Class)null);10. 11. /Bean定義讀取器注冊注解Bean定義的入口方法12. publicvoidregisterBean(ClassannotatedClass,Class.qualifiers)13. registerBean(annotatedClass,null,qualifiers);14. 15. /Bean定義讀取器向容器注冊注解Bean定義類16. publicvoidregisterBean(ClassannotatedClass,Stringname,Class.qualifiers)17. /根據(jù)指定的注解Bean定義類,創(chuàng)建Spring容器中對注解Bean的封裝的數(shù)據(jù)結構18. AnnotatedGenericBeanDefinitionabd=newAnnotatedGenericBeanDefinition(annotatedClass);19. /解析注解Bean定義的作用域,若Scope(prototype),則Bean為原型類型;20. /若Scope(singleton),則Bean為單態(tài)類型21. ScopeMetadatascopeMetadata=this.scopeMetadataResolver.resolveScopeMetadata(abd);22. /為注解Bean定義設置作用域23. abd.setScope(scopeMetadata.getScopeName();24. /為注解Bean定義生成Bean名稱25. StringbeanName=(name!=null?name:this.beanNameGenerator.generateBeanName(abd,this.registry);26. /處理注解Bean定義中的通用注解27. AnnotationConfigUcessCommonDefinitionAnnotations(abd);28. /如果在向容器注冊注解Bean定義時,使用了額外的限定符注解,則解析限定符注解。29. /主要是配置的關于autowiring自動依賴注入裝配的限定條件,即Qualifier30. /注解,Spring自動依賴注入裝配默認是按類型裝配,如果使用Qualifier則按名稱31. if(qualifiers!=null)32. for(Classqualifier:qualifiers)33. /如果配置了Primary注解,設置該Bean為autowiring自動依賴注入裝/配時的首選34. if(Primary.class.equals(qualifier)35. abd.setPrimary(true);36. 37. /如果配置了Lazy注解,則設置該Bean為非延遲初始化,如果沒有配置,38. /則該Bean為預實例化39. elseif(Lazy.class.equals(qualifier)40. abd.setLazyInit(true);41. 42. /如果使用了除Primary和Lazy以外的其他注解,則為該Bean添加一43. /個autowiring自動依賴注入裝配限定符,該Bean在進autowiring44. /自動依賴注入裝配時,根據(jù)名稱裝配限定符指定的Bean45. else46. abd.addQualifier(newAutowireCandidateQualifier(qualifier);47. 48. 49. 50. /創(chuàng)建一個指定Bean名稱的Bean定義對象,封裝注解Bean定義類數(shù)據(jù)51. BeanDefinitionHolderdefinitionHolder=newBeanDefinitionHolder(abd,beanName);52. /根據(jù)注解Bean定義類中配置的作用域,創(chuàng)建相應的代理對象53. definitionHolder=AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata,definitionHolder,this.registry);54. /向IoC容器注冊注解Bean類定義對象BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder,this.registry);55. (1)從上面的源碼我們可以看出,注冊注解Bean定義類的基本步驟:a,需要使用注解元數(shù)據(jù)解析器解析注解Bean中關于作用域的配置。b,使用AnnotationConfigUtils的processCommonDefinitionAnnotations方法處理注解Bean定義類中通用的注解。c,使用AnnotationConfigUtils的applyScopedProxyMode方法創(chuàng)建對于作用域的代理對象。d,通過BeanDefinitionReaderUtils向容器注冊Bean。下面我們繼續(xù)分析這3步的具體實現(xiàn)過程(2).AnnotationScopeMetadataResolver解析作用域元數(shù)據(jù):AnnotationScopeMetadataResolver通過processCommonDefinitionAnnotations方法解析注解Bean定義類的作用域元信息,即判斷注冊的Bean是原生類型(prototype)還是單態(tài)(singleton)類型其源碼如下:1. /解析注解Bean定義類中的作用域元信息2. publicScopeMetadataresolveScopeMetadata(BeanDefinitiondefinition)3. ScopeMetadatametadata=newScopeMetadata();4. if(definitioninstanceofAnnotatedBeanDefinition)5. AnnotatedBeanDefinitionannDef=(AnnotatedBeanDefinition)definition;6. /從注解Bean定義類的屬性中查找屬性為”Scope”的值,即Scope注解的值7. /annDef.getMetadata().getAnnotationAttributes方法將Bean8. /中所有的注解和注解的值存放在一個map集合中9. Mapattributes=10. annDef.getMetadata().getAnnotationAttributes(this.scopeAnnotationType.getName();11. /將獲取到的Scope注解的值設置到要返回的對象中12. if(attributes!=null)13. metadata.setScopeName(String)attributes.get(value);14. /獲取Scope注解中的proxyMode屬性值,在創(chuàng)建代理對象時會用到15. ScopedProxyModeproxyMode=(ScopedProxyMode)attributes.get(proxyMode);16. /如果Scope的proxyMode屬性值為null、DEFAULT或者NO17. if(proxyMode=null|proxyMode=ScopedProxyMode.DEFAULT)18. /設置proxyMode為NO19. proxyMode=this.defaultProxyMode;20. 21. /為返回的元數(shù)據(jù)設置proxyMode22. metadata.setScopedProxyMode(proxyMode);23. 24. 25. /返回解析的作用域元信息對象26. returnmetadata;27. 上述代碼中的annDef.getMetadata().getAnnotationAttributes方法就是獲取對象中指定類型的注解的值。(3).AnnotationConfigUtils處理注解Bean定義類中的通用注解:AnnotationConfigUtils類的processCommonDefinitionAnnotations在向容器注冊Bean之前,首先對注解Bean定義類中的通用Spring注解進行處理源碼如下:1.

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論