黄暁童SPRING学習ノート:DIに対する深い探究


Springの定義 DIに対する初歩的な理解 AOPに対する初歩的な理解 DIに対する深い探究 AOPに対する深い探究 Springの事務管理 Spring MVC
 springの特性の一つはDIであり、DIの鍵はbeanの組立、すなわちシステムの各コンポーネント間の協力関係を作ることである.コンポーネントはspring容器に生存しています.容器はspringの核心であり、springは様々な容器を提供しています.第一はbean工場で、BenFactoryインターフェースです.二つ目はApplication Contectインターフェースです.BenFactoryは最もシンプルな容器で、ベースの注入サポートのみを提供します.後者はBenFactoryをベースに、より多くのシステムサービスを提供します. Springには様々なBenfactoryが実装されていますが、その中で最も一般的なのはXMLプロファイルに基づいてbeanを搭載するXmlBenFactoryです.しかし、XmlBenFactoryを作成するには、このResourceオブジェクトがBenFactoryにXMLファイルを提供しているのです.したがって、ビーンファクトリーを作成します.
BeanFactory  factory  =  new  XmlBeanFactory( new FileSystemResource( “C:/abc.xml” ) );
 これはファイルシステムを通してxmlファイルの初期化BenFactoryを読み取るためのもので、Class PathResource、InputStreamResourceなどの多くの方法があります.しかし、上記のコードを実行するということは、具体化されていません.beanを具体化するには、getBenメソッドを呼び出す必要があります.この方法を呼び出した後、BenFactoryはxmlプロファイルに従ってbeanの属性を設定し、それを実装します. しかし、多くの場合、より強力な機能が必要となります.この時には、Application Contectを使う必要があります.そして、ほとんどの場合、私たちは後者を使います.しかし、springのアプリケーションはコンテキストオブジェクトもよく使われています.コンテキストを読み込むのは簡単です.
ApplicationContext context = new FileSystemXmlApplicationContext(“C:/abc.xml”);
 またはこのように:
ApplicationContext context = new ClassPathXmlApplicationContext(“abc.xml”);
  この時にbeanを獲得する時とBenFactoryを獲得する時は同じです.やはりApple Contact textはBenFactoryから継承されます. 以下、いくつかの例を通して、浅深に述べる.年に一度のJava天才大会が来ました.どの参加者もどんな番組を演じられます.したがって、各参加者はこのインターフェースを実現します.
public  interface  Performer
{ public  void  perform(); }
 
まずはマジシャンが登場します.簡単なビーンです.
public  class  Juggler  implements  Performer {
  private  int  beanBags = 3;
   
  public  Juggler(int  beanBags) {
    this.beanBags = beanBags;  
  }

  public  void  perform(){
    System.out.println("JUGGLING " + beanBags + " BEANBAGS");
  }
}
 
従来の注入方式は以下の通りである.
<bean  id=”duke”  class=”com.alibaba.Juggler”  / >
 
スプリング容器にbeanを搭載すると、クラスのデフォルトのコンストラクタが呼び出されますので、このクラスのインスタンスのbeanBags変数の値は3です.このクラスのインスタンスの変数値は15であるような構成方法によってもよい.
<bean  id=”duke”  class=”com.alibaba.Juggler” >
 <constructor-arg  value=”15”  />
</bean>
 
このように、springはbeanに注入すると、このクラスの重負荷構造関数を呼び出します.いくつかの特殊なコンストラクタのパラメータにオブジェクトが含まれている場合(ベースでないタイプ)は、以下のようにパラメータの値を指定できます.
<constructor-arg  ref=”object-Bean-Id”  />
 
その中の「object-Bean-Id」は別のbeanのidです.
次に、スプリングのsetter注入方式を実証するために、すばらしい楽器演奏家のKennyさんをお招きしました.
public  class  InstrumentKenny  implements  Performer 
{
  public void perform() 
 {
    System.out.print("Playing " + song + " : ");
    instrument.play();
  }
  
  private String song;
  public void setSong(String song) {
    this.song = song;
  }
  
  private Instrument instrument;
  public void setInstrument(Instrument instrument) {
    this.instrument = instrument;
  }
}
 
もちろん、楽器インターフェースを定義する必要があります.
public  interface  Instrument
{
  public void play();
}
 
今、私たちはサクソフォーン楽器を作ります.
public  class  Saxophone  implements  Instrument
{
 public void play() 
 {
 System.out.println("TOOT TOOT TOOT");
 }
}
 
この時、私達は次のような構成をするだけで、Kennyにサックス風を演奏させられます.
<bean  id="saxophone"  class="com.alibaba.Saxophone" />
<bean  id=”kenny”  class=”com.alibaba.InstrumentKenny”>
 <property  name=”song”  value=”Jingle bells” />
 <property  name=”instrument”  ref=” saxophone” />
</bean>
 
 実際には,setterを用いて注入し,構造関数を用いて注入することに変わりはなく,コードはほとんど同じであることが分かった.もしkennyが頭がよくて、ピアノも演奏するなら、私たちはピアノの種類を声明して、配置ファイルを修正するだけでいいです.既存のコードをほとんど修正する必要がなく、これにより松結合の目的が達成された. 今では、kennyは、Instrumentインターフェースを実現する楽器を演奏することができますが、これらの楽器は他の人にも演奏されますので、楽器の個人衛生問題(サカス風は口を使って吹くものです)が発生しました.私たちは内部のbeanを注入することによってこの問題を解決できます.
<bean  id=”kenny”  class=”com.alibaba.InstrumentKenny”>
 <property  name=”song”  value=”Jingle bells” />
 <property  name=”instrument”>
  <bean  class=”com.alibaba. saxophone” />
 </property>
</bean>
 
 内部のbeanは他のbeanに多重化されないので、このbeanはid属性を持つ必要がない.もちろん,構造関数注入方式においても内部beanを用いることができる.
 次に、springの自動注入について説明します.スプリングは四つの自動組立タイプを提供しています.byname、bytype、construct、autdetect.その中で、最も広く使われています.今はkennyがサックスを演奏する構成を思い出します.
<bean  id="saxophone"  class="com.alibaba.Saxophone" />
<bean  id=”kenny”  class=”com.alibaba.InstrumentKenny”>
 <property  name=”song”  value=”Jingle bells” />
 <property  name=”instrument”  ref=” saxophone” />
</bean>
 上記の構成を以下のように変えて、springの自動注入を実現できます.
<bean  id=" instrument"  class="com.alibaba.Saxophone" />
<bean  id=”kenny”  class=”com.alibaba.InstrumentKenny”  autowire=”buName”>
 <property  name=”song”  value=”Jingle bells” />
</bean>
 
 しかし、我々は、autwire="byType"を設定する際に、明示的にあるbeanを組み立てることができ、springは自分でtypeの同じbeanを探す必要がなく、同じタイプのbeanが複数ある場合にはspringが異常を出すことを避けるために、混合方式を使用することができます. これにより,springの自動組立には多くの問題があり,最大の欠点はコードの可読性と透明性の欠如であることがわかった. 私たちはもうスプリングスのbeanへの搭載の基礎知識を理解しました.次に私達はspringの中でbeanの範囲を説明します.springでは、beanの範囲は以下のようになります.singleton、prototype、request、session、global-sessionなどです.
<bean  id=””  class=””  scope=””  />
 
ここで、scopeを指定しないと、デフォルトは単一の例、すなわちsingletonであり、spring容器全体において、beanは一例しかないという意味である.プロトタイプは反対に、使うたびに作成されます.もちろん、他の手段でも、例えば、beanラベルのfactory-method属性を設定して、この種類の工場方法を指定することができます. beanライフサイクルには二つの重要な一環があります.初期化と廃棄です.beanの初期化方法と廃棄方法を指定するのは簡単です.beanタグのinit-method属性とdestroy-methodを設定すればいいです.もちろん、もう一つの方法があります.InitializingBeanとDispsable Beanインターフェースを実現し、その後、afterPropertiesset方法とdestroy方法を実現して、beanの初期化と廃棄を実現します. 次はベルンの継承を見てみましょう.springのbeanラベルには二つの属性があります.parentとabstract.前者はjavaの中のextensに相当して、後者はspring容器を教えるので、このbeanは実用化されてはいけません.例えば、前に述べましたが、kennyはサックスを上手に吹く選手です.彼の配置書類は以下の通りです.
<bean  id="saxophone"  class="com.alibaba.Saxophone" />
<bean  id=”kenny”  class=”com.alibaba.InstrumentKenny”>
 <property  name=”song”  value=”Jingle bells” />
 <property  name=”instrument”  ref=” saxophone” />
</bean>
  しかし、この試合はkennyさんだけでなく、一人でサックスを吹きます.今はdavidさんもサックスを吹きます.そして「Jingle bells」も演奏します.このようにすれば、id以外の2つのbeanを配置するのは多少面倒です.私たちはベルンの継承特性を使用する必要があります.設定は以下の通りです
<bean  id=”baseSaxophonist”  class=”com.alibaba.Instrument”  abstract=”true” >
 <property  name=”song”  value=”Jingle bells” />
 <property  name=”instrument”  ref=” saxophone” />
</bean>
<bean  id=”kenny” parent=”baseSaxophonist” />
  もちろん、今また一人の選手が来たら、彼はサクソフォーンを吹きますが、演奏しているのは「Jingle bells」ではないです.これは既存の親beanが使えないという意味ですか?もちろん違います.私たちは父のbeanの属性をカバーすることもできます.たとえば:
<bean  id=”frank” parent=”baseSaxophonist” >
 <property  name=”song”  value=”another song” />
</bean>
 
 しかし、父のbeanを宣言する時、私達はbeanのclass属性を指定しなくてもいいです.具体的なclassは子供beanから指定します.そうすると、私達はよく使う属性を父のbeanに提出して、各beanに継承させます.各サブbeanは同じタイプではないです.