2、Spring的 IoC詳解(第一個Spring程序)

?

Spring是為了解決企業應用開發的復雜性而創建的一個輕量級的控制反轉(IoC)和面向切面(AOP)的容器框架。在這句話中重點有兩個,一個是IoC,另一個是AOP。今天我們講第一個IoC。

一. IoC理論的背景

  我們都知道,在采用面向對象方法設計的軟件系統中,它的底層實現都是由N個對象組成的,所有的對象通過彼此的合作,最終實現系統的業務邏輯。

  如果我們打開機械式手表的后蓋,就會看到與上面類似的情形,各個齒輪分別帶動時針、分針和秒針順時針旋轉,從而在表盤上產生正確的時間。圖1中描述的就是 這樣的一個齒輪組,它擁有多個獨立的齒輪,這些齒輪相互嚙合在一起,協同工作,共同完成某項任務。我們可以看到,在這樣的齒輪組中,如果有一個齒輪出了問 題,就可能會影響到整個齒輪組的正常運轉。
齒輪組中齒輪之間的嚙合關系,與軟件系統中對象之間的耦合關系非常相似。對象之間的耦合關系是無法避免的,也是必要的,這是協同工作的基礎。現在,伴隨著工業級應用的規模越來越龐大,對象之間的依賴關系也越來越復雜,經常會出現對象之間的多重依賴性關系,因此,架構師和設計師對于系統的分析和設計,將面臨 更大的挑戰。對象之間耦合度過高的系統,必然會出現牽一發而動全身的情形。

  耦合關系不僅會出現在對象與對象之間,也會出現在軟件系統的各模塊之間,以及軟件系統和硬件系統之間。如何降低系統之間、模塊之間和對象之間的耦合度,是軟件工程永遠追求的目標之一。為了解決對象之間的耦合度過高的問題,軟件專家Michael Mattson提出了IOC理論,用來實現對象之間的“解耦”,目前這個理論已經被成功地應用到實踐當中,很多的J2EE項目均采用了IOC框架產品Spring。

2. 什么是控制反轉(IoC)

  IOC是Inversion of Control的縮寫,多數書籍翻譯成“控制反轉”,還有些書籍翻譯成為“控制反向”或者“控制倒置”。
1996年,Michael Mattson在一篇有關探討面向對象框架的文章中,首先提出了IOC 這個概念。對于面向對象設計及編程的基本思想,前面我們已經講了很多了,不再贅述,簡單來說就是把復雜系統分解成相互合作的對象,這些對象類通過封裝以后,內部實現對外部是透明的,從而降低了解決問題的復雜度,而且可以靈活地被重用和擴展。IOC理論提出的觀點大體是這樣的:借助于“第三方”實現具有依 賴關系的對象之間的解耦,如下圖:

  大家看到了吧,由于引進了中間位置的“第三方”,也就是IOC容器,使得A、B、C、D這4個對象沒有了耦合關系,齒輪之間的傳動全部依靠“第三方”了, 全部對象的控制權全部上繳給“第三方”IOC容器,所以,IOC容器成了整個系統的關鍵核心,它起到了一種類似“粘合劑”的作用,把系統中的所有對象粘合 在一起發揮作用,如果沒有這個“粘合劑”,對象與對象之間會彼此失去聯系,這就是有人把IOC容器比喻成“粘合劑”的由來。
  我們再來做個試驗:把上圖中間的IOC容器拿掉,然后再來看看這套系統:

?  我們現在看到的畫面,就是我們要實現整個系統所需要完成的全部內容。這時候,A、B、C、D這4個對象之間已經沒有了耦合關系,彼此毫無聯系,這樣的話, 當你在實現A的時候,根本無須再去考慮B、C和D了,對象之間的依賴關系已經降低到了最低程度。所以,如果真能實現IOC容器,對于系統開發而言,這將是 一件多么美好的事情,參與開發的每一成員只要實現自己的類就可以了,跟別人沒有任何關系!
  我們再來看看,控制反轉(IOC)到底為什么要起這么個名字?我們來對比一下:
  軟件系統在沒有引入IOC容器之前,如圖1所示,對象A依賴于對象B,那么對象A在初始化或者運行到某一點的時候,自己必須主動去創建對象B或者使用已經創建的對象B。無論是創建還是使用對象B,控制權都在自己手上。
  軟件系統在引入IOC容器之后,這種情形就完全改變了,如圖3所示,由于IOC容器的加入,對象A與對象B之間失去了直接聯系,所以,當對象A運行到需要對象B的時候,IOC容器會主動創建一個對象B注入到對象A需要的地方。
  通過前后的對比,我們不難看出來:對象A獲得依賴對象B的過程,由主動行為變為了被動行為,控制權顛倒過來了,這就是“控制反轉”這個名稱的由來。

3.? IOC的別名:依賴注入(DI)

  2004年,Martin Fowler探討了同一個問題,既然IOC是控制反轉,那么到底是“哪些方面的控制被反轉了呢?”,經過詳細地分析和論證后,他得出了答案:“獲得依賴對象的過程被反轉了”。控制被反轉之后,獲得依賴對象的過程由自身管理變為了由IOC容器主動注入。于是,他給“控制反轉”取了一個更合適的名字叫做“依賴 注入(Dependency Injection)”。他的這個答案,實際上給出了實現IOC的方法:注入。所謂依賴注入,就是由IOC容器在運行期間,動態地將某種依賴關系注入到對象之中

  所以,依賴注入(DI)和控制反轉(IOC)是從不同的角度的描述的同一件事情,就是指通過引入IOC容器,利用依賴關系注入的方式,實現對象之間的解耦
  我們舉一個生活中的例子,來幫助理解依賴注入的過程。大家對USB接口和USB設備應該都很熟悉吧,USB為我們使用電腦提供了很大的方便,現在有很多的外部設備都支持USB接口。

  現在,我們利用電腦主機和USB接口來實現一個任務:從外部USB設備讀取一個文件。
  電腦主機讀取文件的時候,它一點也不會關心USB接口上連接的是什么外部設備,而且它確實也無須知道。它的任務就是讀取USB接口,掛接的外部設備只要符 合USB接口標準即可。所以,如果我給電腦主機連接上一個U盤,那么主機就從U盤上讀取文件;如果我給電腦主機連接上一個外置硬盤,那么電腦主機就從外置 硬盤上讀取文件。掛接外部設備的權力由我作主,即控制權歸我,至于USB接口掛接的是什么設備,電腦主機是決定不了,它只能被動的接受。電腦主機需要外部 設備的時候,根本不用它告訴我,我就會主動幫它掛上它想要的外部設備,你看我的服務是多么的到位。這就是我們生活中常見的一個依賴注入的例子。在這個過程 中,我就起到了IOC容器的作用
  通過這個例子,依賴注入的思路已經非常清楚:當電腦主機讀取文件的時候,我就把它所要依賴的外部設備,幫他掛接上。整個外部設備注入的過程和一個被依賴的對象在系統運行時被注入另外一個對象內部的過程完全一樣。
  我們把依賴注入應用到軟件系統中,再來描述一下這個過程:
  對象A依賴于對象B,當對象 A需要用到對象B的時候,IOC容器就會立即創建一個對象B送給對象A。IOC容器就是一個對象制造工廠,你需要什么,它會給你送去,你直接使用就行了, 而再也不用去關心你所用的東西是如何制成的,也不用關心最后是怎么被銷毀的,這一切全部由IOC容器包辦。
  在傳統的實現中,由程序內部代碼來控制組件之間的關系。我們經常使用new關鍵字來實現兩個組件之間關系的組合,這種實現方式會造成組件之間耦合。IOC 很好地解決了該問題,它將實現組件間關系從程序內部提到外部容器,也就是說由容器在運行期將組件間的某種依賴關系動態注入組件中。

4.? IOC為我們帶來了什么好處

  我們還是從USB的例子說起,使用USB外部設備比使用內置硬盤,到底帶來什么好處?
  第一、USB設備作為電腦主機的外部設備,在插入主機之前,與電腦主機沒有任何的關系,只有被我們連接在一起之后,兩者才發生聯系,具有相關性。所以,無 論兩者中的任何一方出現什么的問題,都不會影響另一方的運行。這種特性體現在軟件工程中,就是可維護性比較好,非常便于進行單元測試,便于調試程序和診斷 故障。代碼中的每一個Class都可以單獨測試,彼此之間互不影響,只要保證自身的功能無誤即可,這就是組件之間低耦合或者無耦合帶來的好處。
  第二、USB設備和電腦主機的之間無關性,還帶來了另外一個好處,生產USB設備的廠商和生產電腦主機的廠商完全可以是互不相干的人,各干各事,他們之間 唯一需要遵守的就是USB接口標準。這種特性體現在軟件開發過程中,好處可是太大了。每個開發團隊的成員都只需要關心實現自身的業務邏輯,完全不用去關心 其它的人工作進展,因為你的任務跟別人沒有任何關系,你的任務可以單獨測試,你的任務也不用依賴于別人的組件,再也不用扯不清責任了。所以,在一個大中型 項目中,團隊成員分工明確、責任明晰,很容易將一個大的任務劃分為細小的任務,開發效率和產品質量必將得到大幅度的提高。
  第三、同一個USB外部設備可以插接到任何支持USB的設備,可以插接到電腦主機,也可以插接到DV機,USB外部設備可以被反復利用。在軟件工程中,這 種特性就是可復用性好,我們可以把具有普遍性的常用組件獨立出來,反復利用到項目中的其它部分,或者是其它項目,當然這也是面向對象的基本特征。顯 然,IOC不僅更好地貫徹了這個原則,提高了模塊的可復用性。符合接口標準的實現,都可以插接到支持此標準的模塊中。
  第四、同USB外部設備一樣,模塊具有熱插拔特性。IOC生成對象的方式轉為外置方式,也就是把對象生成放在配置文件里進行定義,這樣,當我們更換一個實現子類將會變得很簡單,只要修改配置文件就可以了,完全具有熱插撥的特性。
  以上幾點好處,難道還不足以打動我們,讓我們在項目開發過程中使用IOC框架嗎?

5.? IOC容器的技術剖析

  IOC中最基本的技術就是“反射(Reflection)”編程,目前.Net C#、Java和PHP5等語言均支持,其中PHP5的技術書籍中,有時候也被翻譯成“映射”。有關反射的概念和用法,大家應該都很清楚,通俗來講就是根據給出的類名(字符串方式)來動態地生成對象。這種編程方式可以讓對象在生成時才決定到底是哪一種對象。反射的應用是很廣泛的,很多的成熟的框架,比如象Java中的Hibernate、Spring框架,.Net中 NHibernate、Spring.Net框架都是把“反射”做為最基本的技術手段。
  反射技術其實很早就出現了,但一直被忽略,沒有被進一步的利用。當時的反射編程方式相對于正常的對象生成方式要慢至少得10倍。現在的反射技術經過改良優化,已經非常成熟,反射方式生成對象和通常對象生成方式,速度已經相差不大了,大約為1-2倍的差距。
  我們可以把IOC容器的工作模式看做是工廠模式的升華,可以把IOC容器看 作是一個工廠,這個工廠里要生產的對象都在配置文件中給出定義,然后利用編程語言的的反射編程,根據配置文件中給出的類名生成相應的對象。從實現來 看,IOC是把以前在工廠方法里寫死的對象生成代碼,改變為由配置文件來定義,也就是把工廠和對象生成這兩者獨立分隔開來,目的就是提高靈活性和可維護 性。

6.? IOC容器的一些產品?  

  Sun ONE技術體系下的IOC容器有:輕量級的有Spring、Guice、Pico Container、Avalon、HiveMind;重量級的有EJB;不輕不重的有JBoss,Jdon等等。Spring框架作為Java開發中 SSH(Struts、Spring、Hibernate)三劍客之一,大中小項目中都有使用,非常成熟,應用廣泛,EJB在關鍵性的工業級項目中也被使 用,比如某些電信業務。

  .Net技術體系下的IOC容器有:Spring.Net、Castle等等。Spring.Net是從Java的Spring移植過來的IOC容 器,Castle的IOC容器就是Windsor部分。它們均是輕量級的框架,比較成熟,其中Spring.Net已經被逐漸應用于各種項目中。

7. 使用IOC框架應該注意什么

  使用IOC框架產品能夠給我們的開發過程帶來很大的好處,但是也要充分認識引入IOC框架的缺點,做到心中有數,杜絕濫用框架。
  第一、軟件系統中由于引入了第三方IOC容器,生成對象的步驟變得有些復雜,本來是兩者之間的事情,又憑空多出一道手續,所以,我們在剛開始使用IOC框 架的時候,會感覺系統變得不太直觀。所以,引入了一個全新的框架,就會增加團隊成員學習和認識的培訓成本,并且在以后的運行維護中,還得讓新加入者具備同 樣的知識體系。
  第二、由于IOC容器生成對象是通過反射方式,在運行效率上有一定的損耗。如果你要追求運行效率的話,就必須對此進行權衡。
  第三、具體到IOC框架產品(比如:Spring)來講,需要進行大量的配制工作,比較繁瑣,對于一些小的項目而言,客觀上也可能加大一些工作成本。
  第四、IOC框架產品本身的成熟度需要進行評估,如果引入一個不成熟的IOC框架產品,那么會影響到整個項目,所以這也是一個隱性的風險。
  我們大體可以得出這樣的結論:一些工作量不大的項目或者產品,不太適合使用IOC框架產品。另外,如果團隊成員的知識能力欠缺,對于IOC框架產品缺乏深 入的理解,也不要貿然引入。最后,特別強調運行效率的項目或者產品,也不太適合引入IOC框架產品,象WEB2.0網站就是這種情況。

IoC概念回顧

? ? ? ?控制反轉(Inversion of Control)是一個重要的面向對象編程的法則來削減計算機程序的耦合問題。 它還有一個名字叫做依賴注入(Dependency Injection)。IoC不是什么技術,它是一種設計模式。

?

實例演示

? ? ? ?為了更好的說明IoC,我為大家舉一個簡單的例子,如有這樣一個描述:某公司新成立了一個項目組,項目組有若干成員和一個項目組長,項目組成立后第一次開會上,作為項目組長的小李按照慣例首先做了簡短的自我介紹。

? ? ? ?根據上述的描述,如果我們寫出如下代碼和類圖:

復制代碼
    public class Li {    public void introduce() {System.out.println("大家好,我是小李");}}public class Team {public void firstMeeting() {Li li = new Li();li.introduce();}}
復制代碼
? ? ? 具體類圖如下:


? ? ? ?上述的代碼,應該說基本完成了相關的需求,但是仔細考慮之后就會發現,上述的代碼是根據具體的場景描述進行的,并沒有進行抽象,這樣就導致我們不能靈活的安排項目組長去做開場,即根據現在的代碼,開場自我介紹被綁定給了小李而不能安排給其他人。為了解決上述的問題,我們引入首先引入Leader接口,相關代碼和類圖如下:?

復制代碼
    public interface Leader {public void introduce();}public class Li implements Leader {@Overridepublic void introduce() {System.out.println("大家好,我是小李");}}public class Team {public void firstMeeting() {Leader li = new Li();li.introduce();}}
復制代碼

? ? ? ?具體類圖如下:

?? ? ? ?雖然上述的代碼可以讓我們安排給其他成員開場,但是我們可以看出Team類同時依賴Leader接口和Li類,并沒有達到我們所期望的Team僅僅依賴于Leader接口的目的,如何解決這個問題呢?當然是引入Boss,由Boss決定具體由誰擔任項目組長。具體類圖和代碼如下:

復制代碼
    public interface Leader {public void introduce();}public class Li implements Leader {@Overridepublic void introduce() {System.out.println("大家好,我是小李");}}public class Team {public void firstMetting(Leader leader){leader.introduce();}}public class Boss {public void direct(){Leader leader = new Li();Team team = new Team();team.firstMetting(leader);}}
復制代碼

?? ? ? ?具體類圖如下:

? ? ? ? 通過以上代碼和圖示,我們可以看出,通過引入老板類,我們將項目小組和具體由誰擔任項目組長進行解耦。

? ? ? ?對應上述例子,我們再來講解一下IoC,IoC從字面上看分為控制和反轉,控制在上面的實例中就是具體由誰擔任項目組長,而反轉就是將決定誰擔任項目組長轉移到Boss類中。通俗理解就是將接口的具體實現類(Li)的控制權從調用類(Team)中分離轉交給第三方(Boss)決定。

? ? ? ?到此為止,IoC的概念我們就已經講完了,具體Spring中如何實現呢?

一、第一個Spring程序

1、建立如下的項目結構

2、在項目的src下創建com.spring包下創建Student.java

 1 package com.spring;
 2 /**
 3  * 
 4  * @author Holly老師
 5  *
 6  */
 7 public class Student {
 8     private String name;
 9     private String sex;
10     public String getName() {
11         return name;
12     }
13     public void setName(String name) {
14         this.name = name;
15     }
16     public String getSex() {
17         return sex;
18     }
19     public void setSex(String sex) {
20         this.sex = sex;
21     }
22     @Override
23     public String toString() {
24         return "Student [name=" + name + ", sex=" + sex + "]";
25     }
26     
27 
28 }
Student.java

3、在src下創建applicationContext.xml文件

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans" 
 3 xmlns:aop="http://www.springframework.org/schema/aop" 
 4 xmlns:context="http://www.springframework.org/schema/context" 
 5 xmlns:tx="http://www.springframework.org/schema/tx" 
 6 xmlns:mvc="http://www.springframework.org/schema/mvc" 
 7 xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
 8 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 9 xsi:schemaLocation="http://www.springframework.org/schema/beans 
10 http://www.springframework.org/schema/beans/spring-beans.xsd 
11 http://www.springframework.org/schema/aop 
12 http://www.springframework.org/schema/aop/spring-aop.xsd 
13 http://www.springframework.org/schema/context
14 http://www.springframework.org/schema/context/spring-context.xsd 
15 http://www.springframework.org/schema/tx
16 http://www.springframework.org/schema/tx/spring-tx.xsd 
17 http://www.springframework.org/schema/mvc
18 http://www.springframework.org/schema/mvc/spring-mvc.xsd 
19 ">
20   <!-- IOC依賴注入,給對象注入數據 -->
21   <!-- 1.
22    bean節點相當于:Student stuent=new Student();
23    bean的id就相當于對象名,class是對象的類型全路徑 -->
24   <bean id="student" class="com.spring.Student">
25       <!-- 1.1 為對象賦值,代理對象通過setter方法賦值 -->
26       <!-- 1.2 
27          property屬性節點的name值必須和Student類的屬性名保持一致
28                  相當于 student.setName("揚名");  
29        -->
30       <property name="name" value="揚名"/>
31       <property name="age" value="18"/>
32   </bean>
33   
34      <!-- 2.創建HelloSpring的bean節點:
35          HelloSpring helloSpring=new HelloSpring();
36       -->
37   <bean id="helloSpring" class="com.spring.HelloSpring">
38      <!-- 2.1 給Student類型的stu對象賦值,helloSpring.setStu(student); -->
39      <property name="stu" ref="student"/>
40      
41      <!-- 2.2賦值方式1:給:helloSpring.setWho("Spring") -->
42      <property name="who">
43        <value>Spring</value>
44      </property>
45     
46      <!-- 2.3賦值方式2:給helloSpring.setYou("holly");-->
47      <property name="you" value="holly"/>
48   </bean>
49 </beans>
applicationContext.xml

?

4、在com.spring包下創建HelloSpring.java

 1 package com.spring;
 2 
 3 public class HelloSpring {
 4     private Student stu=null;
 5     private String who=null;
 6     private String you=null;
 7     public Student getStu() {
 8         return stu;
 9     }
10     public void setStu(Student stu) {
11         this.stu = stu;
12     }
13     public String getWho() {
14         return who;
15     }
16     public void setWho(String who) {
17         this.who = who;
18     }
19     public String getYou() {
20         return you;
21     }
22     public void setYou(String you) {
23         this.you = you;
24     }
25     /**
26      * 打印信息方法:
27      */
28     public void print(){
29         System.out.println("Hello"+this.getWho());
30         System.out.println("you是:"+this.getYou());
31     }
32 
33 }
HelloSpring.java

?

5、在com.test包下創建Test.java 運的效果

 1 package com.test;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 import com.spring.HelloSpring;
 7 
 8 public class Test {
 9 
10     /**
11      * @param args
12      */
13     public static void main(String[] args) {
14        //1.讀取xml文件
15         ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
16     
17        /*2.通過ApplicationContext對象的getBean("Xxx")
18         * 獲取xml文件中bean的id為Xxx的節點對象
19         */
20         HelloSpring hs=(HelloSpring) ac.getBean("helloSpring");
21         
22         //3.調用HelloSpring中的print方法
23         hs.print();
24         
25         //4.打印HelloSpring中類型為Student的stu對象的值
26         System.out.println(hs.getStu());
27     }
28 
29 }
Test.java

?

二、使用IOC注入Dao

1、創建如下項目結構

2、在com.entity包下創建Classes.java

 1 package com.entity;
 2 
 3 public class Classes {
 4     private int cid;
 5     private String cname;
 6     
 7     public Classes() {
 8     }
 9 
10     public Classes(int cid, String cname) {
11         this.cid = cid;
12         this.cname = cname;
13     }
14 
15     public int getCid() {
16         return cid;
17     }
18 
19     public void setCid(int cid) {
20         this.cid = cid;
21     }
22 
23     public String getCname() {
24         return cname;
25     }
26 
27     public void setCname(String cname) {
28         this.cname = cname;
29     }
30 
31     @Override
32     public String toString() {
33         return "Classes [cid=" + cid + ", cname=" + cname + "]";
34     }
35     
36 
37 }
Classes.java

3、在com.entity包下創建Student.java

 1 package com.entity;
 2 /**
 3  * 學生表
 4  * @author Dell
 5  *
 6  */
 7 public class Student {
 8     private String sid;
 9     private String sname;
10     private String sex;
11     private Classes cla;
12     
13     public Student() {
14     }
15     public Student(String sid, String sname, String sex, Classes cla) {
16         this.sid = sid;
17         this.sname = sname;
18         this.sex = sex;
19         this.cla = cla;
20     }
21     public String getSid() {
22         return sid;
23     }
24     public void setSid(String sid) {
25         this.sid = sid;
26     }
27     public String getSname() {
28         return sname;
29     }
30     public void setSname(String sname) {
31         this.sname = sname;
32     }
33     public String getSex() {
34         return sex;
35     }
36     public void setSex(String sex) {
37         this.sex = sex;
38     }
39     public Classes getCla() {
40         return cla;
41     }
42     public void setCla(Classes cla) {
43         this.cla = cla;
44     }
45     @Override
46     public String toString() {
47         return "Student [cla=" + cla + ", sex=" + sex + ", sid=" + sid
48                 + ", sname=" + sname + "]";
49     }
50     
51     
52 
53 }
Student.java

4、在src下創建applicationContext.xml文件

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3  xmlns:aop="http://www.springframework.org/schema/aop" 
 4  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 5  xsi:schemaLocation="http://www.springframework.org/schema/beans 
 6  http://www.springframework.org/schema/beans/spring-beans.xsd ">
 7    <!-- 定義班級bean -->
 8    <bean id="classes" class="com.entity.Classes">
 9       <property name="cid" value="1"/>
10       <property name="cname" value="TB13"/>
11    </bean>
12    
13    <!-- 定義學生bean -->
14    <bean id="stu" class="com.entity.Student">  
15      <property name="sid" value="1"/>
16      <property name="sname" value="holly"/>
17      <property name="sex" value="女"/>
18      <!-- 注入班級bean -->
19      <!-- 注入方式1:設置注入  -->
20      <property name="cla" ref="classes"/>
21    </bean>
22  
23 </beans>
applicationContext.xml

5、在com.spring包下創建Test.java

 1 package com.spring;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 import com.entity.Student;
 7 
 8 public class Test {
 9 
10     /**
11      * @param args
12      */
13     public static void main(String[] args) {
14         //加載讀取xml文件
15         ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
16         
17         //通過配置文件的bean的id獲取某個節點內容,注意在要注入classes的student類中一定要有getter和setter方法
18         Student stu=(Student) ac.getBean("stu");
19         System.out.println(stu);
20 
21     }
22 
23 }
Test.java

6、運行效果如下:

?

轉載于:https://www.cnblogs.com/holly8/p/5532950.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/372951.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/372951.shtml
英文地址,請注明出處:http://en.pswp.cn/news/372951.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

排除服務器簡單系統故障方法,引導CD排除服務器故障方法有哪些?

盡管Linux系統以穩定可靠著稱&#xff0c;但由于硬件問題有時仍會崩潰/或無法引。針對這一問題&#xff0c;最好的解決辦法就是使用Linux系統引導CD。為了方便讀者&#xff0c;筆者在下面列出了安裝Red Hat Linux 8。0的最必須步驟。為安裝過程作筆記在Red Hat Linux系統典型安…

js 獲取father_(原創)Node.JS實戰26:強大的工作池。收藏吧!你一定會用的到。...

在實際項目中&#xff0c;如果遇到需要大計算量的操作&#xff0c;按需fork&#xff08;分叉&#xff09;其實不是一個好的選擇。因為fork的子進程也是V8&#xff08;NodeJS的核心引擎&#xff09;的新實例&#xff0c;每創建一個新實例&#xff0c;需要約30毫秒啟動時間&#…

具有ReadWriteLock的Java并發

編寫多線程Java應用程序并不是小菜一碟。 必須格外小心&#xff0c;因為同步不良會使您的應用程序一s不振。 JVM堆由所有線程共享。 如果多個線程需要同時使用相同的對象或靜態類變量&#xff0c;則必須謹慎管理對共享數據的線程訪問。 從1.5版開始&#xff0c;JSDK中包含了在并…

修復steam服務器失敗,steam服務器鏈接失敗

steam服務器鏈接失敗 內容精選換一換當NTP服務器異常時產生該告警。當NTP服務器異常消除時&#xff0c;該告警恢復。主OMS節點配置的NTP服務器異常&#xff0c;可能會導致主OMS節點與外部服務器不能同步時間&#xff0c;集群時間可能會產生飄移。NTP服務器網絡異常。與NTP服務器…

qemu-kvm簡單使用

qemu-kvm主要有以下幾個選項: -snapshot: 創建快照-m: 指定內存大小-smp: 指定處理器個數-cpu: 指定CPU類型-name: 設置虛擬機名稱-vnc: 使用vnc連接-boot: 指定啟動相關的選項-net: 指定網卡相關的選項-drive: 指定硬盤/光盤相關的選項qemu-kvm -m 128 -name first -smp 2 -dr…

將jar添加到發布目錄_第32批免購置稅新能源車型目錄發布;通用BEV3平臺將入華...

1、第32批免購置稅新能源車型目錄發布&#xff0c;幾何X/理想ONE等283款車型入選6月2日&#xff0c;工信部發布《免征車輛購置稅的新能源汽車車型目錄(第三十二批)》&#xff0c;共有283款新能源車型入選。其中新能源乘用車方面包括&#xff0c;一汽大眾Q2L/e-BORA、東風風神E7…

HPROF –內存泄漏分析教程

本文將為您提供有關如何通過生成和分析Sun HotSpot JVM HPROF堆轉儲文件來分析JVM內存泄漏問題的教程。 一個現實的案例研究將用于此目的&#xff1a;Weblogic 9.2內存泄漏影響Weblogic Admin服務器。 環境規格 Java EE服務器&#xff1a;Oracle Weblogic Server 9.2 MP1 中…

mq服務器與客戶端消息同步,使用 ActiveMQ 實現JMS 異步調用

目錄簡介服務之間的同步調用&#xff0c;可以使用 HTTP 或 RPC 來完成&#xff0c;但并非所有的調用都需要同步&#xff0c;有些場景下&#xff0c;當客戶端調用服務端時&#xff0c;并不需要等待服務端做出響應&#xff0c;此時就應該使用異步調用。異步調用的常用方式是基于 …

多個數字數組_七個問題幫助初學者深入理解Java數組

短文漲姿勢&#xff0c;看了不白看&#xff0c;不關注等啥&#xff1f;幾乎所有的高級語言當中&#xff0c;都提供了一種叫做”數組”的東西&#xff0c;Java語言當然也不例外。我們通過數組可以很方便的存儲和管理一組數據。因為在Java語言當中使用數組非常的方便&#xff0c;…

java 異常練習題1

建立exception包&#xff0c;建立Bank類&#xff0c;類中有變量double balance表示存款,Bank類的構造方法能增加存款&#xff0c;Bank類中有取款的發方法withDrawal(double dAmount),當取款的數額大于存款時,拋出InsufficientFundsException,取款數額為負數&#xff0c;拋出Nag…

大話設計模式讀書筆記--6.原型模式

簡單的復制粘貼極有可能造成重復代碼的災難, 但是java中提供了克隆的功能, 如果一個對象創建過程復雜,又要頻繁使用, 在初始化信息不發生變化的情況下,應當采取克隆而不是new一個對象 定義 原型模式: 用原型實例指定創建對象的種類,并且通過拷貝這些原型創建新的對象 也就是說,…

Java 7#8:測試臺上的NIO.2文件通道

關于新JDK 7功能的另一篇博客文章。 這次我正在寫有關新的AnsynchronousFileChannel類的文章。 我將在兩周內深入分析新的JDK 7功能&#xff0c;并決定連續編號我的帖子。 只是為了確保我不會感到困惑&#xff1a;-)這是我關于Java 7的第七篇文章&#xff08;我承認–碰巧–這也…

5頁面title樣式修改_認識html:實現網站頁面是這么簡單的一回事

互聯網時代人們通過上網瀏覽信息&#xff0c;打開瀏覽器上網看到豐富的圖文、視頻、音樂等多媒體信息&#xff0c;一系列信息反饋和視覺沖擊之后&#xff0c;您有沒有想過&#xff0c;互聯網這么發達的時代&#xff0c;您覺得花一點點時間學會做個網站頁面不真香&#xff1f;概…

iOS指南針

前言&#xff1a; 這個小項目使用到了CoreLocation框架里面的設備朝向功能&#xff0c;對CoreLocation感興趣的可以翻一下之前的文章 在另一個博客站有朋友發現一個尷尬的問題&#xff08;圖片的東西2個方向是不對的&#xff09;&#xff0c;原諒我的大意&#xff0c;趕時間就直…

OSGI –模塊化您的應用程序

由于我是模塊化&#xff0c;低耦合&#xff0c;高凝聚力等的大力擁護者&#xff0c;所以…… 我相信這項技術是我們使用Java平臺創建應用程序的突破。 使用OSGi&#xff0c;創建高度可擴展的應用程序非常簡單&#xff0c;例如參見Eclipse IDE。 我的目的不是要深入展示該技術的…

jq的鏈式調用.end();

jq的鏈式調用.end(); 先上code <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><style>li{list-style: none;width: 100px;height:20px;border:1px solid #ff0000;display: …

三、自定義視圖、視圖控制器

1.自定義視圖 自定義視圖&#xff1a;系統標準UI之外&#xff0c;自己組合而出的新的視圖。在實際開發中&#xff0c;我們經常需要自己定義視圖&#xff0c;積累自己的代碼庫。自己封裝的視圖&#xff0c;能像系統提供的UI控件一樣用于多個項目中&#xff0c;這樣可以提高我們的…

程序如何在兩個gpu卡上并行運行_深度學習分布式訓練相關介紹 - Part 1 多GPU訓練...

本篇文章主要是對深度學習中運用多GPU進行訓練的一些基本的知識點進行的一個梳理文章中的內容都是經過認真地分析&#xff0c;并且盡量做到有所考證拋磚引玉&#xff0c;希望可以給大家有更多的啟發&#xff0c;并能有所收獲介紹大多數時候&#xff0c;梯度下降算法的訓練需要較…

集成Spring和JavaServer Faces:改進的模板

隨著2.0版的發布&#xff0c;Facelet模板成為JSF規范的核心部分。 使用<ui&#xff1a;composition>和<ui&#xff1a;decorate>標記&#xff0c;可以輕松構建復雜的頁面&#xff0c;同時仍保持標記清晰。 模板在創建HTML表單時特別有用&#xff0c;但是不幸的是&a…

whmcs模板路徑

whmcs網站根目錄 比如你的域名是server.nongbin.vip&#xff0c;你需要cd /home/wwwroot/server.nongbin.vip&#xff0c;該目錄下然后&#xff0c;cd template/ 給文件夾下就是你上傳的模板文件夾轉載于:https://www.cnblogs.com/nongbin/p/6412108.html