前言:Spring框架是我們進行企業(yè)級開發(fā)的最常用框架,本章我們將了解Spring框架,并學習Spring的IOC特性以及IOC的實現(xiàn)原理:注解和反射。Spring框架簡介Spring是一種輕量級的控制反轉(zhuǎn)(IOC)和面向切面編程(AOP)的容器框架,能夠為企業(yè)級開發(fā)提供一站式服務(wù)。 Spring的優(yōu)點有 1.方便解耦,簡化開發(fā) 通過Spring提供的IoC容器,我們可以將對象之間的依賴關(guān)系交由Spring進行控制,避免硬編碼所造成的過度程序耦合。有了Spring,用戶不必再為單實例模式類、屬性文件解析等這些很底層的需求編寫代碼,可以更專注于上層的應(yīng)用。 2.AOP編程的支持 通過Spring提供的AOP功能,方便進行面向切面的編程,許多不容易用傳統(tǒng)OOP實現(xiàn)的功能可以通過AOP輕松應(yīng)付。 3.聲明式事務(wù)的支持 在Spring中,我們可以從單調(diào)煩悶的事務(wù)管理代碼中解脫出來,通過聲明式方式靈活地進行事務(wù)的管理,提高開發(fā)效率和質(zhì)量。 4.方便程序的測試 可以用非容器依賴的編程方式進行幾乎所有的測試工作,在Spring里,測試不再是昂貴的操作,而是隨手可做的事情。例如:Spring對Junit4支持,可以通過注解方便的測試Spring程序。 5.方便集成各種優(yōu)秀框架 Spring不排斥各種優(yōu)秀的開源框架,相反,Spring可以降低各種框架的使用難度,Spring提供了對各種優(yōu)秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持。 6.降低Java EE API的使用難度 Spring對很多難用的Java EE API(如JDBC,JavaMail,遠程調(diào)用等)提供了一個薄薄的封裝層,通過Spring的簡易封裝,這些Java EE API的使用難度大為降低。 Spring的組成![]() Spring Core:Spring 框架的核心。Spring其它組件都依賴于核心組件,主要通過BeanFactory提供IOC等服務(wù)。 Spring Context:Sprin上下文是一個配置文件,向 Spring框架提供上下文信息。Spring 上下文包括企業(yè)服務(wù),例如JNDI、EJB、電子郵件、國際化、校驗和調(diào)度功能。 Spring AOP:通過配置管理特性,Spring AOP 模塊直接將面向切面的編程功能集成到了 Spring 框架中。 Spring ORM:Spring 框架插入了若干個ORM框架,從而提供了 ORM 的對象關(guān)系工具,其中包括JDO、Hibernate和iBatisSQL Map。所有這些都遵從 Spring 的通用事務(wù)和 DAO 異常層次結(jié)構(gòu)。 Spring DAO: DAO抽象層提供了有意義的異常層次結(jié)構(gòu),可用該結(jié)構(gòu)來管理異常處理和不同數(shù)據(jù)庫供應(yīng)商拋出的錯誤消息。異常層次結(jié)構(gòu)簡化了錯誤處理,并且極大地降低了需要編寫的異常代碼數(shù)量(例如打開和關(guān)閉連接)。Spring DAO 的面向 JDBC 的異常遵從通用的 DAO 異常層次結(jié)構(gòu)。 Spring Web: Web 上下文模塊建立在應(yīng)用程序上下文模塊之上,為基于 Web 的應(yīng)用程序提供了上下文。所以,Spring框架支持與 Jakarta Struts 的集成。Web 模塊還簡化了處理多部分請求以及將請求參數(shù)綁定到域?qū)ο蟮墓ぷ鳌?/span> Spring Web MVC: 為 web 應(yīng)用提供了模型視圖控制(MVC)和 REST Web 服務(wù)的實現(xiàn)。Spring 的 MVC 框架可以使領(lǐng)域模型代碼和 web 表單完全地分離,且可以與 Spring 框架的其它所有功能進行集成。 IOC和DIIOC(Inverse Of Control)是控制反轉(zhuǎn)的意思,作用是降低對象之間的耦合度。 一般情況下我們直接在對象內(nèi)部通過new進行創(chuàng)建對象,是程序主動去創(chuàng)建依賴對象;而IoC是有專門一個容器來創(chuàng)建這些對象,即由Ioc容器來控制對象的創(chuàng)建;這樣就是由容器來控制對象,而不是由我們的對象來控制,這樣就完成了控制反轉(zhuǎn)。 DI(Dependency Injection)即“依賴注入”:是組件之間依賴關(guān)系由容器在運行期決定,形象的說,即由容器動態(tài)的將某個依賴關(guān)系注入到組件之中。依賴注入的目的并非為軟件系統(tǒng)帶來更多功能,而是為了提升組件重用的頻率,并為系統(tǒng)搭建一個靈活、可擴展的平臺。通過依賴注入機制,我們只需要通過簡單的配置,而無需任何代碼就可指定目標需要的資源,完成自身的業(yè)務(wù)邏輯,而不需要關(guān)心具體的資源來自何處,由誰實現(xiàn)。 IOC的原理:注解+反射下面的案例講解了IOC的原理,模擬為電腦配置不同的CPU和內(nèi)存,CPU有AMD和INTEL兩種,內(nèi)存有DDR8G和DDR16G兩種 1. /** 2. * CPU接口 3. */ 4. public interface Cpu { 5. 6. void run(); 7. } 8. /** 9. * 內(nèi)存接口 10. */ 11. public interface Memory { 12. 13. void read(); 14. void write(); 15. } 16. /** 17. * AMD的CPU 18. */ 19. public class AMDCpu implements Cpu { 20. 21. public void run() { 22. System.out.println("AMD的CPU正在運行...."); 23. } 24. } 25. /** 26. * Intel的CPU 27. */ 28. public class IntelCpu implements Cpu{ 29. 30. public void run() { 31. System.out.println("Intel的CPU正在運行...."); 32. } 33. } 34. /** 35. * DDR8G的內(nèi)存 36. */ 37. public class DDR8GMemory implements Memory { 38. public void read() { 39. System.out.println("使用DDR8G的內(nèi)存讀取數(shù)據(jù)...."); 40. } 41. 42. public void write() { 43. System.out.println("使用DDR8G的內(nèi)存寫入數(shù)據(jù)...."); 44. } 45. } 46. /** 47. * DDR16G的內(nèi)存 48. */ 49. public class DDR16GMemory implements Memory { 50. public void read() { 51. System.out.println("使用DDR16G的內(nèi)存讀取數(shù)據(jù)...."); 52. } 53. 54. public void write() { 55. System.out.println("使用DDR16G的內(nèi)存寫入數(shù)據(jù)...."); 56. } 57. } 58. public class TestComputer { 59. 60. @Test 61. public void testComputer(){ 62. //硬編碼方式創(chuàng)建對象 63. Computer computer = new Computer(); 64. Cpu cpu = new IntelCpu(); 65. Memory memory = new DDR16GMemory(); 66. computer.setCpu(cpu); 67. computer.setMemory(memory); 68. computer.start(); 69. } 70. } 上面是使用硬編碼方式創(chuàng)建電腦的CPU和內(nèi)存屬性,代碼和具體的子類緊密耦合,不利于后期的維護和擴展。 修改的思路是:不由讓程序主動創(chuàng)建去創(chuàng)建CPU和內(nèi)存對象,而是通過注解方式標記CPU和內(nèi)存的類型,使用反射將CPU和內(nèi)存的對象注入到電腦的屬性中。 添加代碼: 71. /** 72. * 電腦組件的注解 73. */ 74. @Retention(RetentionPolicy.RUNTIME) 75. @Target(ElementType.FIELD) 76. public @interface MyComponent { 77. /** 78. * 組件類型 79. * @return 80. */ 81. Class componentClass(); 82. } 83. /** 84. * 電腦類 85. */ 86. public class Computer { 87. 88. @MyComponent(componentClass = IntelCpu.class) 89. private Cpu cpu; 90. 91. @MyComponent(componentClass = DDR8GMemory.class) 92. private Memory memory; 93. 94. ....} 95. 96. public class TestComputer { 97. 98. @Test 99. public void testComputer(){ 100. //通過反射和注解,將cpu和memory屬性注入進去 101. try { 102. //獲得Computer類型 103. Class<Computer> computerClass = Computer.class; 104. //創(chuàng)建Computer對象 105. Computer computer = computerClass.newInstance(); 106. //獲得Computer對象的屬性 107. Field[] fields = computerClass.getDeclaredFields(); 108. //遍歷屬性 109. for(Field field : fields){ 110. //獲得屬性上定義的MyComponent注解 111. MyComponent anno = field.getDeclaredAnnotation(MyComponent.class); 112. //獲得配置的組件類型 113. Class aClass = anno.componentClass(); 114. //創(chuàng)建該組件的對象 115. Object comp = aClass.newInstance(); 116. //調(diào)用set方法賦值給屬性 117. String name = field.getName(); 118. name = "set" + name.substring(0,1).toUpperCase() + name.substring(1); 119. //通過方法名和參數(shù)類型獲得方法 120. Method method = computerClass.getDeclaredMethod(name, field.getType()); 121. //調(diào)用方法 122. method.invoke(computer,comp); 123. } 124. //啟動電腦 125. computer.start(); 126. } catch (Exception e) { 127. e.printStackTrace(); 128. } 129. } 130. } 程序如上面修改后,后期如果需要修改電腦的配置,只需要修改注解配置的類型,就可以注入不同的電腦組件,這樣就降低了代碼間的耦合性,維護代碼變得比較簡單。 @MyComponent(componentClass = AMDCpu.class) private Cpu cpu; @MyComponent(componentClass = DDR16GMemory.class) private Memory memory; 總結(jié)IOC(控制反轉(zhuǎn))是Spring最重要的原理,它將創(chuàng)建對象的主動權(quán)交給Spring容器,Spring程序只需要進行一些配置,就可以使用不同的對象,極大的降低了代碼耦合性,提高了程序的靈活性,IOC的實現(xiàn)原理是反射機制。 |
|
來自: 好程序員IT > 《Java培訓教程》