Spring in Action入門之裝配管理Bean


注明:這篇文章一是當成學習筆記,二是給大家提供另一個快速理解學習Spring的參考。歡迎留言討論,持續更新中~

(該部分是Spring的入門和Spring容器裝配管理Bean的方法)

第一章 開始Spring之旅

  • Applet可以用來創建動態的Web應用,在html文件中通過<applet>標識,一種已經被淘汰的技術。
<applet code="Bubbles.class" width="350" height="350">
Java applet that draws animated bubbles.
</applet>

POJO實質上可以理解為簡單的實體類,如果項目中使用了Hibernate框架,有一個關聯的***.hbm.xml文件,就可以使對象與數據庫中的表對應。

負責輕量級POJO開發就是Spring框架,由此引入Spring。。。

1.1 Spring是什么?

Spring是一個輕量級的DI和AOP容器框架,目標:高內聚、松耦合。

  • DI(Dependency Injection,依賴注入):對象不是從容器中查找它的依賴類,而是容器在實例化對象的時候主動將它的依賴類注入給它。
  • AOP(Aspect Oriented Programming,面向切面):通過將業務邏輯從應用服務中分離出來,實現了內聚開發。(比如:開發者可以先專注開發一個裸系統,然后再加上用戶系統,如Spring Security)
  • Spring容器:可以通過配置來設定你的Bean是單一實例,還是每次請求產生一個實例,用容器去管理應用對象的生命周期和配置。
    • scope="singleton"單實例模式,默認配置;   scope="prototype" 每次請求都會創建一個實例。
    • 配合Struts2時候要配置scope="prototype" ,因為Struts2中的Action是非單例的,每次請求都會創建一個新的Action,讓Struts2的Action由Spring創建,Spring默認創建出的對象都是單實例的,要加上scope="prototype",讓spring每次請求創建一個實例。
    • 如果響應類中沒有成員變量,那么單例模式是線程安全的,否則需要對全局變量做保護,信號量控制。
<bean id="adTagFacade"  class="outfox.ead.adbrand.domain.impl.AdTagFacadeImpl" scope="singleton">
<property name="adTagDao" ref="adTagDao" />
</bean>

 1.2 開始Spring之旅

還是從Hello World!開始~

<bean id="greetingSerivice" class="com.springinaction.hello.GreetingServiceImpl">
    <property name="greeting" value="Hello World!"/>
</bean>

通過配置<bean>元素中的<property>設置屬性值,告訴Spring容器通過調用Bean的setGreetring方法設置其屬性值,(BeanFactory)factory.getBean("greetingService")的時候實例化類,同時注入greetring的值,最后打印出來。

1.3 理解依賴注入

耦合是一個雙頭怪物,一方面,緊密耦合的代碼難以測試,難以重用難以理解,帶來典型的“摧毀大堤”bug。另一方面,完全沒有耦合的代碼什么也做不了。耦合是必須的,但需要小心管理。

減少耦合的一個通常的做法是將具體實現隱藏在接口下面,這樣具體實現的替換不會影響到引用類。

DI的全部:簡言之,協調依賴對象之間合作的責任從對象自身中轉移出來。(通過XML配置,Spring容器去管理)

1.4 應用AOP

DI是軟件組件松散連接成為可能,AOP讓你能夠捕捉應用中經常使用的功能,把它轉化為可重用組件

以下是將log轉化成了切面:

<aop:config>
    <aop:aspect ref="log"> //聲明一個切面,log提供了該切面的功能,這里是一個普通的bean。
        <aop:pointcut id="pointCut" expression="excution(*.doTask(..))"/> //切面的切入點,執行doTask可以出發該切入點
        <aop:before method="doTaskBefore" pointcut-ref="pointCut"/>   //log下的doTaskBefore方法應該在切入點之前調用,下同
        <aop:after-returning method="doTaskAfter" pointcut-ref="pointCut"/>
    </aop:aspect>
</aop:config>

 

第2章 基本Bean裝配

2.1 容納你的Bean

  • Spring的容器:Bean工廠 and 應用上下文
    • BeanFactory:

常用的是根據XML文件中的定義裝載Bean,比如:

BeanFactory factory = new XMLBeanFactory(new FileSystemResource("c:/beans.xml"));

Bean是被延遲載入到Bean工廠中的,就是說Bean工廠會立即把Bean定義信息載入進來,但是Bean只有在被需要的時候才被實例化。為了從BeanFactory得到一個Bean,只要簡單的調用getBean()方法。

MyBean myBean = (MyBean) factory.getBean("myBean");

工廠就會實例化Bean並且使用依賴注入設置Bean的屬性

    • 應用上下文:

也有諸多實現,比如ClassPathXmlApplicationContext

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

應用上下文ApplicationContext接口擴展自BeanFactory接口,一個重要的區別是關於單實例Bean是如何被載入的。應用上下文會在上下文啟動后預載入所有的單實例Bean。通過預載入單實例Bean,確保當你需要的時候它們已經准備好了,你的應用不需要等待它們被創建。

  • 注意區別:應用上下文比起Bean工廠提供了一些附加功能,幾乎所有的應用系統都選擇ApplicationContext而不是BeanFactory,只有在資源很少的情況下,才會考慮采用Beanfactory,如在移動設備上。

2.2 創建Bean

兩種方式:

  • 通過構造函數注入依賴,優點少些了Setter代碼,強制使用強依賴契約,因為如果沒有提供所有需要的依賴,一個Bean就無法被實例化了。
<bean id="duke" class="com.springinaction.springidol.ProticJuggler">
    <constructor-arg value="15"/>
    <constructor-arg ref="sonnet29"/>
</bean>
  • Setter方法注入依賴,優點當依賴很多的時候,比較靈活。利於自身的繼承。因為構造函數是不能被繼承的。子類只能調用super()方法給父類的私有變量賦值。(推薦)
<bean id="duke" class="com.springinaction.springidol.ProticJuggler">
    <property name="beanBags" value="15">
</bean>

2.3 注入Bean屬性

  • 內部Bean,一種注入依賴Bean的方式,但是無法復用,內部Bean只用於注入,且不能被其他Bean所引用。
一般寫法:
<bean id="piano" class="com.springinaction.springidol.Piano"/>
<bean id="kenny" class="...">
<property name="instrument" ref="piano">
</bean>

若要用內部類如下:
<bean id="kenny" class="...">
<property name="instrument">
<bean class="om.springinaction.springidol.Piano">
</property>
</bean>

 

  • Spring配置基本類型(通過value)和其他類(通過ref),但value和ref只有在屬性是單一的時候才有效。那么當屬性是復數(就是集合)時,Spring怎么做呢?
  • Spring裝配支持的集合類型:<list> <set> <map> <props>,常用<list>,<map>
List:屬性可重復,對應java里的collection,常用 <property name="instruments">
<list>
<ref bean="guitar">
<ref bean="cymbal">
</list>
</property>

Set:屬性不重復
<property name="instruments">
<set>
<ref bean="guitar">
<ref bean="cymbal">
<ref bean="cymbal"> //自動忽略重復的屬性
</set>
</property>

Maps:key-value的映射,常用 <property name="instruments">
<map>
<entry key="GUITAR" value-ref="guitar">
<entry key =......>
</map>
</property>

Properties:配置String-to-String的映射
<property name="instruments">
<props>
<prop key="GUITAR">STRUM STRUM STRUM</prop>
<prop key="CYMBAL">CRASH CRASH CRASH</prop>
</props>
</property>

2.4 自動裝配

四種自動裝配的類型,byName byType constructor autodetect,自動裝配雖然節省了XML代碼,但是也帶來了很多問題,比如屬性名字設計時候相當小心,重構代碼時候要連帶修改,自動裝配的最大缺點就是缺乏透明,一般不采用這個Spring IOC的自動裝配特性。

2.5 控制Bean創建

初始化和銷毀Bean,兩種方式:

  • 在聲明<bean>的時候加上init-method和destroy-method參數,指定在Bean初始化的時候調用的方法。(推薦使用)
  • java實現類的時候,實現InitializingBean和DisposableBean的afterPropertiesSet和destory方法,spring會允許它們勾入到Bean的生命周期中。(缺點:應用Bean和Spring API相互耦合)

第三章 高級Bean裝配

3.1Spring配置實現繼承

為了實現Bean的繼承,<bean>元素提供了兩個特殊屬性:

  • parent:指明Bean的id。他對於<bean>的作用就相當於關鍵字extents對於Java類的作用。
  • abstract:如果設置為true,就表示<bean>聲明是抽象的,不能被Spring實例化。
<bean id="baseBean" class="..." abstract="true">
<property name=""  ref="" />
</bean>

<bean id="childBean" parent="baseBean" />

3.2 方法注入(不常用)

  • 基本方法替換<replaced-method>
  • 獲取器注入<lookup-method>

把一個方法(一般是抽象的)聲明為返回某種類型的Bean

public abstract Instrument getInstrument();

xml配置覆蓋:
<lookup-method name="getInstrument" bean="guitar">

//這就類似如下的java代碼

publc Instrument getInstrument() {
    ApplicationContext ctx = ...;
    return (Instrument)  ctx.getBean("guitar");  
}

3.3腳本化Bean(Ruby Groovy BeanShell)

比如Ruby的實現:

<lang:jruby id="lime"
script-source="classpath:com/springinaction/scriptring/Lime.rb"
script-interfaces="com.springinaction.scripting.Lime" />

使用腳本實現特定代碼,而不是用靜態編譯的Java編寫它的一個最大好處在於,我們可以隨時修改它,而不必重新編譯或重新部署程序。當然取決於Spring刷新腳本的頻率refresh-check-delay

萌萌的IT人,IT人的樂園


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM