Javaクラスでは、ロッドジョンソンという名の偉大な男が、最初のJavaエンタープライズレベルの開発が混oticとした状態にあることを発見しました。
そのため、問題を解決できる一般的なインフラストラクチャを作成することにしました。
インターフェイス指向のプログラミングが変化を最小限に抑え、拡大と変化を促進することもできると固く信じているためです。そのため、次のインターフェイスを書きました。
混oticとした状態で最初に作成するのは、すべてのオブジェクトの母親であるBeanFactoryであり、それによって、それが育てるすべてのオブジェクトと属性を取得することができます。
ジョンソンは、元のマザービーンファクトリーで、1つまたは複数ではなく豆のオブジェクトのセットを取得したいと思ったらどうでしょうか。さらに、母親の子供もパートナーを産みたいとしたらどうでしょうか?したがって、ジョンソンは、一連のビーンオブジェクトを操作するためにlistableBeanFactoryを作成しました。たとえば、GetBeansofTypeは、同じタイプの豆のセットを取得できます。 getParentBeanFactoryなど、複数のBeanFactoryの階層的な問題を解決するために作成されたHierarchicalBeanFactoryがBeanFactoryの親工場を取得できます。
このBeanFactoryは最終的にアプリケーションで使用されるため、BeanFactoryにアプリケーションに移動する機能を与える必要があります。 BeanFactoryでは、豆を入手する方法、豆の種類など、豆に関連する行動を検討する必要があります。また、アプリケーションで能力を提供したい場合は、アプリケーション名、起動時間、IDなど、アプリケーション自体に関連する動作や属性など、より多くを考慮する必要があるため、JohnsonはApplicationContextを作成することを考えました。ジョンソンは、このApplicationContextは多くのことを行うことができ、パラメーター化された国際化されたテキスト情報を処理できる必要があるため、Messagesourceインターフェイスを追加する必要があると考えました。コンポーネントを分離するためにイベントを公開できる必要があるため、ApplicationEventPublisherインターフェイスがあります。リソースファイルを取得できる必要があるため、ResourcePatterNresolverインターフェイスがあります。さまざまな環境で異なる処理オブジェクトを持つことができる必要があるため、環境に敏感なインターフェイスがあります。
ApplicationContextこれらのすべてのインターフェイスを継承します。
しかし、最も重要なことは、BeanFactoryとApplicationContextの両方が設定可能な機能を持つ必要があるため、サブインテリアが構成可能なBeanFactoryとconfigureAbleapplicationContextがあることです。さらに、当時はWebは非常に重要な傾向であり、他のアプリケーションと比較して少しユニークであったため、ServletContextを取得する必要があるため、WebApplicationContextがありました。
これまでのところ、ジョンソンはインターフェイスの動作について抽象的な考えをしており、それらを詳細に実装していません。
作成されたBeanFactoryとApplicationContextを見ると、Johnsonは、システム全体を機能させる方法の本当の解決策がなかったため、その日の仕事が終わっていないことに気付きました。
Johosonが最初に考えるのは、この実装にはどのような機能があるべきかということです。もちろん、前述のAutoWirecapableBeanFactory、ListableBeanFactory、ConfigureableBeanFactoryを含める必要があります。したがって、ConfigureAblElistableBeanFactoryが作成されました。第二に、Beanオブジェクトのいくつかの能力を考慮する必要があります。1つはエイリアスの能力です。 2つ目は、シングルトンオブジェクトを保存する機能です。 3つ目は、キャッシュする機能です。それらは、それぞれSimplealiaSregistryクラス、DefaultSingletonBeanRegistryクラス、およびFactoryBeanRegistrySupportクラスに実装されています。
最後に、DefaultListableBeanFactoryが作成されました。これは、春のすべてのIOC工場のプロトタイプであり、BeanFactoryの最初の実在の子供です。この子供は非常に重要であり、IOC容器の独立した作成の基礎となっています。拡張されて使用されている場合、それらのほとんどは継承されているか、組み合わせて使用されます。
defaultListableBeanFactoryを初期化する場合は、次のコードを使用できます
classPathResource res = new ClassPathResource( "ApplicationContext.xml"); DefaultListableBeanFactory f = new DefaultListableBeanFactory(); XmlbeanDefinitionReader r = new xmlbeandefinitionReader(f); R.LoadBeanDefinitions(res);
次に、ジョンソンは、BeanFactoryには比較的包括的なデフォルトの実装があると考えていたので、ApplicationContextはどうですか?そのため、Johnsonは3つの重要なApplicationContextの実装をたゆまぬものに作成しました:FilesystemXMLApplicationContext、ClassPathXMLApplicationContext、AnnotationConfigWebapplicationContext(実際、ポートレットの取り扱いや操作ウェブなど、さらに多くがあります)
ジョンソンが最初に考慮したのは、スプリングスタートアッププロセスをどのように行うかです。低いレベルのすべてのクラスを再利用できるように、比較的抽象的なレベルに配置する必要があります。そこで、彼はAbstractApplicationContextを使用してconfigureableapplicationContextを実装しました。また、非常に重要な関数、つまり、リソースの形式でファイルをロードすることもあります。これには、リソースをリソースクラスに抽象化し、ポジショニングリソースの特定の実装をResourceloAderに抽象化する必要があります。 AbstractApplicationContextは、この関数を提供するためにDefaultroSourceloAderを継承する必要があります。 AbstractApplicationContextは、スタートアッププロセス全体を完了しました(Godは翌日に完了するように配置しました)が、BeanFactoryを管理しませんでした。したがって、そのサブクラスのAbstractrefreshableapplicationContextはこれを具体的に行い、refressbeanfactory、closebeanfactoryを実装し、getBeanFactoryはBeanFactoryのライフサイクルを具体的に管理しますが、AbstractrefreshableableadicationContextはまだ構成されたすべての豆をロードしません。構成されたリソースをロードする場所では、ファイルシステムにXML ApplicationContextを読み取るFilesyStyxmLapplicationContextなど、実際に下部サブクラスに移動して実行します。 classPathXMLApplicationContextは、このApplicationContextをクラスロードパスに読み取ることです。 annotationConfigwebapplicationContextクラスファイルの注釈から豆をロードし、スプリングスキャンはこれから始まります。
メインフレームが確立されているのを見て、ジョンソンは笑顔に満足して眠りに落ちました。
初日、ジョンソンは春の全体的なフレームワークを完了しました。
2日目に、ジョンソンは実際に以前の問題に対処する準備をしていました。たとえば、春のコンテナ初期化プロセス。図に示されているように、ジョンソンはこのプロセスを多くのサブプロセスに分割します。これはすべて、豆を積み込むという壮大な目標を中心に取り組んでいます。
このプロセスは、AbstractApplicationContextの更新方法に配置されます。コードは次のとおりです。ジョンソンは更新プロセスを多くのサブプロセスに分割し、これらのサブプロセスは同じ抽象レベルです。この書き方は、将来の世代にロールモデルを与えることです。
public void refresh()Throws BeanSexception、IllegalStateException {同期(this.startupshutdownmonitor){//このコンテキストをリフレッシュのために準備します。 prepererefresh(); //サブクラスに、内部豆工場を更新するように伝えます。 ConfigureAblElistableBeanFactory BeanFactory = gotainFreshBeanFactory(); //このコンテキストで使用するためにBean Factoryを準備します。 prepareBeanFactory(BeanFactory); {//コンテキストサブクラスでビーン工場の後処理を許可します。 PostProcessBeanFactory(BeanFactory); //コンテキストで豆として登録された工場プロセッサを呼び出します。 InvokeBeanFactoryPostProcessors(BeanFactory); // Beanの作成を傍受するBeanプロセッサを登録します。 RegisterBeanPostProcessors(BeanFactory); //このコンテキストのメッセージソースを初期化します。 initmessageSource(); //このコンテキストのイベントマルチカスターを初期化します。 initapplicationeventMulticaster(); //特定のコンテキストサブクラスで他の特別な豆を初期化します。 onrefresh(); //リスナーの豆を確認して登録します。 RegisterListeners(); //残りのすべての(怠lazyinit)シングルトンをすべてインスタンス化します。 FinishBeanFactoryInitialization(BeanFactory); //最終ステップ:対応するイベントを公開します。 finishrefresh(); } catch(beansexception ex){//ぶら下がっているリソースを避けるために、すでに作成されたシングルトンを破壊します。 DestroyBeans(); //「アクティブ」フラグをリセットします。 cancelrefresh(ex); //発信者に例外を伝播します。 Exを投げる; }}}より高いレベルで見ると、これらのプロセスは実際にいくつかの側面を中心に展開します。1。ライフサイクルを更新します。 2。BeanFactoryの初期化と準備。 3. BeanDefinitionを生成および登録します。 4。BeanFactoryPostprocessor; 5.メッセージ、イベント、リスナーを設定します。
1。リフレッシュライフサイクル
PrayereFreshでは、このプロセスは主にログを記録し、Springが開始され、プロパティリソース(Serlvetの一部のリソースの初期化など)を初期化し、プロパティリソース(価値のないキーのみを書くなど)の検証を示します。
onrefreshの目的は、いくつかの特別なApplicationContextを提供して、更新プロセス中に拡張できるようにすることです。現在の使用法のほとんどは、サーブレットアプリケーションのコンテキストのテーマを設定することです
finistrefresh、ライフサイクルプロセッサの初期化、リフレッシュのための出版イベントなど、いくつかの仕上げ作業を行います。
CancelRefreshは、主に例外が発生したときに現在の状態を非アクティブに変更します。
2。BeanFactoryの初期化と準備
ジョンソンは、BeanFactoryの負荷を発揮し、初期化されたときにBeanを透過的に登録する必要があると考えているため、私のカプセル化は外の世界で非常に成功しているため、このステップは実際に多くのことを行います。次の図は多くの手順を省略し、キーポイントのみをリストします。
AbstractApplicationContextはrefressbeanFactoryを呼び出します。最初に既存のBeanFactoryをチェックして閉じてから、新しいBeanFactoryを作成し、この工場を使用してすべてのBeanDefinitionをロードします。
その中でも、LoadBeanDefinitionはさまざまな実装のためにサブクラスに引き渡されます。たとえば、AbstractXmlapplicationContextは主にXMLを介して読み取りされます。 annotationConfigwebapplicationContextの実装は、クラスの豆をスキャンするためにスキャナーを呼び出します。
3. BeanDefinitionを生成および登録します
XML構成を解析した後、defaultBeanDefinitionDocumentReaderのparsedeFaultElementメソッドは、XMLの要素に基づいて対応する処理を実行します。その中で、Bean要素に遭遇すると、BeanDefinitionReaderutilsのRegisterBeanDefinitionメソッドが最終的に呼び出されます。この方法で渡されたパラメーターはBeanDefinitionRegistryです。これは、実際にdefaultListableBeanFactoryの登録済みの定義方法を呼び出してBeanDefinitionを登録します(DefaultListableBeanFactoryはBeanDefinitionRegistryを実装します)。
4。BeanFactoryPostprocessor
BeanFactory Postprocessorは、サブクラスを柔軟にするためにSpringが提供する方法です。春には2つのステップがあります。PostProcessBeanFactory、InvokeBeanFactoryPostProcessorsです。 RegisterBeanPostProcessorsは、Beanの初期化の前後にBeanを拡張するために使用されるすべてのBeanPostProcessorsをインスタンス化して呼び出します。
5.メッセージ、イベント、リスナーを設定します
デフォルトのメッセージソースをMessageSourceに設定します。工場に件名が既にある場合は、このmessageSourceを使用してください。イベントマルチカスターはsimpleapplicationeventMulticasterです。工場にapplicationEventMulticasterが既にある場合は、このApplicationEventMulticasterを使用して、すべてのアプリケーションリスナーを登録してイベントを受信します。
MessageSourceは、国際的なリソースファイルの重要な方法です。 Springは、ApplicationContextのメッセージソースをサポートしています。
Springは、java.util.resourcebundleを使用してメッセージを抽出するために、メッセージソースのデフォルトの実装を提供します。 Springは、特別なIDを持つBeanをメッセージソースとして設定し、i18nのファイル名を設定することにより、ApproachContext.getMessage()からのメッセージに直接アクセスできます。 JSPの場合、Spring:メッセージタグからメッセージにアクセスすることもできます。
イベント:イベントは比較的重要な分離メカニズムです。 Springは、Core ApplicationContextに導入されました。その原則は比較的単純です。一方で、イベントジェネレーターはイベントを送信できます。一方、イベントリスナーはイベントに応答できるようです。特定の実装は、基本的に、ジェネレーターにイベントリスナーコレクションを保持し、このイベントリスナーコレクションのすべてのリスナー(つまり、参加)を「登録」します。
春には、ApplicationContextはイベントジェネレーターとして使用され、ApplicationListenersはリスナーコレクションとして使用され、ApplicationEventMulticasterはイベントの公開に使用されます。
イベントを公開するためのいくつかのステップ:
サブスクリプション:最初はリスナーコレクションへのAddApplicationListener。
パブリッシュ:ApplicationContextはApplicationEventPublisherを継承し、PublishEventを実装します。このメソッドは、最初にこのApplicationContextのアプリケーションリステナーコレクションを通過し、各リスナーのOnApplicationEventを呼び出すため、各リスナーに通知されます。このステップが完了すると、ApplicationContextの親のすべてのApplicationListenersに対して同じイベントが公開されます。
イベントの公開は非常に一般的です。私たち自身のアプリケーションがこのイベントパブリッシングを使用できるだけでなく、Spring Framework自体もイベントパブリッシングを使用しています。春のイベントのいくつかのアプリケーションは次のとおりです。
contextrefreshedeventはfinantrefreshで公開され、リフレッシュが終了し、リスナーに通知することを示します。 ApplicationContextでは、開始および停止メソッドは、コンテキストの開始または終了を示すイベントを公開します。
ジョンソンが春のメインフレームワークと操作プロセスを作成した後、彼はスプリングが多くの柔軟な拡張場所を提供することを発見しました。そのため、ジョンソンは3日目にこれらの柔軟な拡張使用を発表する準備をしています。
1。BeanPostProcessor。 BeanPostProcessorは、Beanの作成が完了した後、拡張インターフェイスを提供します。 Beanが作成された後に何らかの処理を行う必要がある場合、BeanPostProcessorが好ましい方法です。
2。意識。注入された豆は、その容器の一部を知る必要があります。 Springは、Beannameawareなど、BeannameawareなどのCallbacksを完了します。これにより、Beanがその名前を知ることができます。 BeanFactoryAwareは、BeanがBeanFactoryのApplicationContextAwareを理解させることができます。これにより、BeanはApplicationContextを動作させます。このようにして、春に注入された豆はより広い範囲のことをすることができます。
BeanPostProcessorの拡張のために、Spring自体には、認識した豆を識別する方法の例があります。認識した豆は比較的特別な豆であり、春にはいくつかの追加の属性が必要です。では、スプリングは注入プロセスにどのように使用されますか?実際、Springはコア処理プロセスでそれを書き込むのではなく、ApplicationContextAwareProcessor、BeanPostProcessorに入れ、最後にInvokeawareInterfacesに入れて、BeanとInjectに対応する属性を決定します。このアプローチでは、BeanPostProcessorを使用して、別の拡張使用を完了します。これは非常に優れています。
private void invokeawareInterfaces(object bean){if(bean instanceof area){if(bean instanceof entumintionaware){((環境)bean).setenvironment(this.applicationContext.getEnvironment(); } if(bean instance of embeddedValueresolveraware){((embeddedValueresolveraware)bean).setembeddedValueresolver(新しいEmbeddedValueresolver(this.ApplicationContext.getBeanFactory()); } if(bean instance of resourceloaderaware){((resourceloaderaware)bean).setresourceloader(this.applicationContext); } if(bean instanceof applicationEventPublisheraware){((ApproachEventPublisheraware)Bean).SetApplicationEventPublisher(this.ApplicationContext); } if(bean instance of messagesourceaware){((messagesourceaware)bean).setmessageSource(this.applicationContext); } if(bean instanceof applicationContextAware){((ApproachContextAware)bean).SetApplicationContext(this.ApplicationContext); }}}認識を使用するためのより多くのルールがあります。たとえば、次のコードはApplicationContextを知覚できます。 SpringがこのBeanを作成した後、ApplicationContextを挿入するため、このコンテキストを使用してイベントパブリッシングを完了できます。
Public Class HellobeanはApplicationContextAware {private applicationContext ApplicationContext;プライベートストリングhelloword = "hello!world!"; public void setApplicationContext(applicationContext Context){this.ApplicationContext = Context; } public void sethellod(string helloword){this.helloword = helloword; } public string gethellodord(){applicationContext.publishevent(new PropertyGetTedEvent( "[" + helloword + "] is gotted")); Hellowordを返します。 }} 3。BeanFactoryPostProcessor、このポストプロセッサは通常、BeanFactoryによって作成された拡張インターフェイスを処理するために使用されます。例は次のとおりです。この豆を注入した後、豆すべての作成後に注入された豆の数を自動的に印刷します。
パブリッククラスのBeanCounterは、BeanFactoryPostProcessor {@Override Public Public PostProcessBeanFactory(configureAbleListableBeanFactory BeanFactory)BeanSexception {System.out.Println(BeanFactory.getBeanDefinitionCount())をスローします。 }} 4。FactoryBean。 Factorybeanは特別な豆であり、スプリング容器への注入と本物の豆の生成を可能にするため、この方法で定義できます。 Factorybean自体は豆であり、豆を提供する能力を持っています。以下は、FactoryBeanの呼び出しから始まり、Springがこの豆を使用する方法について話します。
普通の豆と工場の豆を区別するには、春にはそれらを判断し、特別に処理するプロセスも必要です。このプロセスは、AbstractBeanFactoryのgetObjectforbeaninstanceにあります
保護されたオブジェクトGetObjectForBeanInstance(Object BeanInstance、String Name、String BeanName、rootBeanDefinition MBD){//呼び出しコードに工場が工場でない場合は工場を再参照しようとしないでください。 if(beanfactutils.isfactorydereference(name)&&!(beaninstance instance of factorybean)){throw beanisnotafactoryexception(transformedbeanname(name)、beaninstance.getclass()); } //これで、Beanインスタンスがあります。これは通常の豆または工場のインスタンスです。 //それが工場の場合、//発信者が実際に工場への参照を望んでいる場合を除き、それを使用してBeanインスタンスを作成します。 if(!(FactorybeanのBeaninstance Instance)|| BeanFactututils.IsfactoryDereference(name)){return beaninstance; } object object = null; if(mbd == null){object = getCachedObjectForfactoryBean(beanName); } if(object == null){//工場からbeanインスタンスを返します。 Factorybean <? // Singletonの場合、FactoryBeanから取得したキャッシュオブジェクト。 if(mbd == null && containsbeandefinition(beanname)){mbd = getmergedlocalbeandefinition(beanname); } boolean synthetic =(mbd!= null && mbd.issynthetic()); object = getObjectfromFactoryBean(Factory、BeanName、!Synthetic); }オブジェクトを返します。 }それが普通の豆である場合、それは直接返され、それがFactoryBeanである場合、最終呼び出しはFactory.getObjectに電話して特定のオブジェクトを返します。春全体を抽象的な工場と考え、抽象豆を生産するとき、工場は必要なオブジェクトを生産する特定の工場です。
春には工場出荷時の多くの用途があります。比較的一般的な例を示すために、HibernateのSessionFactoryを統合する場合、localsessionFactorybeanは通常注入されますが、このSessionFactoryは実際には普通の豆ではありません。構成ファイルに注入するだけで生成できます。多くのカスタマイズされた部品があるため、Springはこの豆を工場にし、生産オブジェクトを制御します。