春のソース(9)@Autowired注釈実装の原則(春豆自動組立)

実装@Autowiredノート、実際には、春の豆の自動組立工程。ソースコードを見て@Autowiredコメントセクションでは、我々は@Autowiredが実装AutowiredAnnotationBeanPostProcessorポストプロセッサによって達成されていることがわかります。

AutowiredAnnotationBeanPostProcessor类图


PriorityOrdered:ポストプロセッサのAutowiredAnnotationBeanPostProcessor優先いることを確認し
たBeanFactoryビーンコンテナによって直接取得することができAutowiredAnnotationBeanPostProcessor:BeanFactoryAware
ポストプロセッサBeanの初期化の前と後に実行:BeanPostProcessor
InstantiationAwareBeanPostProcessor:インスタンス化豆と豆の前と後の属性値を設定しますポストプロセッサが実行
SmartInstantiationAwareBeanPostProcessorを:豆は、このようなタイプのコンストラクタビーンビーンなどの予測と確認として、インテリジェントポストプロセッサをインスタンス化します。
MergedBeanDefinitionPostProcessor:統合定義情報のビーン。
私たちが最初にこれらのポストプロセッサの上に導入し、分析前に自動アセンブリ。

ポストプロセッサは、紹介
BeanPostProcessor
二つの方法、postProcessBeforeInitializationとpostProcessAfterInitializationがあるBeanPostProcessorを。これらは、(例えばInitializingBean afterPropertiesSet法のinitメソッドの方法をカスタマイズする前または後に)、この時点で、豆のプロパティ値は、任意の豆初期化コールバックの前または後に完了充填された実行、およびBeanインスタンス我々が返す必要がある可能性がありさ元のインスタンスは、パッケージの種類です。このようなFactoryBeanのを返すように。

InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessorはBeanPostProcessorインタフェースから継承されました。メインマルチは、次の3つの方法を提供します。

postProcessBeforeInstantiation
ターゲットオブジェクトを呼び出す前にあるビーン、ビーンが効果的にBeanのインスタンス化されるデフォルトのターゲットを防止するようにオブジェクトは、オブジェクトを委任することができます返さインスタンス化されます。

オブジェクトresolveBeforeInstantiation保護(文字列のbeanName、RootBeanDefinition MBD){
オブジェクトBean = NULL;
IF(!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)){
//確かBeanクラスはAT実はこの点を解決していることを確認します。
IF(mbd.isSynthetic! ()&& hasInstantiationAwareBeanPostProcessors()){
クラスたtargetType = determineTargetType(のbeanName、MBD)<?>、
!IF(たtargetType = NULL){
豆= applyBeanPostProcessorsBeforeInstantiation(たtargetType、のbeanName);
!IF(豆= NULL){
//この場合はメソッドがnull以外のオブジェクトを返し、ビーンの作成プロセスは短絡となります。
postProcessAfterInitializationコールバックからのさらなる処理のため//のみアプリケーション構成BeanPostProcessors
ビーン= applyBeanPostProcessorsAfterInitialization(豆、のbeanName);
}
}
}
mbd.beforeInstantiationResolved =(豆= nullを!)。
}
Beanを返します。
}

オブジェクトapplyBeanPostProcessorsBeforeInstantiation保護(クラスたbeanClass、のbeanName文字列<?>){
(BeanPostProcessor BP:getBeanPostProcessors())のために{
IF(BP InstantiationAwareBeanPostProcessorのinstanceof){
InstantiationAwareBeanPostProcessor IBP =(InstantiationAwareBeanPostProcessor)BP;
Beanインスタンスの後に対象オブジェクトの実行前//処理方法の
オブジェクトibp.postProcessBeforeInstantiation結果=(たbeanClass、のbeanName);
IF(=ヌルを結果!){
リターン結果;
}
}
}
戻りNULL;
}
このメソッドがnull以外のオブジェクトを返す場合、我々が見ることができるソースに従います、豆は、短絡を作成するプロセスになります。postProcessAfterInitializationコールバックの構成BeanPostProcessorsからのみさらに処理アプリケーション。

postProcessAfterInstantiation
方法は、(明示的または自動組立性を介して)充填された豆の特性が、スプリングをインスタンス化した後、コンストラクタ又はファクトリメソッドの動作を実行する前に発生しています。これは、自動組立を開始する前に、与えられたカスタムフィールド注入Beanインスタンスのコールバック春上で実行されます。このメソッドがfalseを返す場合、それは、ポストプロセッサInstantiationAwareBeanPostProcessor次のブロックが実行され、実行ロジックは、その後の充填性を防止します。

postProcessPropertyValuesの
それらが処理された後、工場には、豆の前に設定され、指定された属性値に適用されます。セッターの「必要な」Beanのプロパティの注釈に基づいて、例えば、すべての依存関係かどうかを調べることができます。また、通常、元のPropertyValuesに基づいてMutablePropertyValuesの新しいインスタンスを作成することで、交換用のプロパティ値を適用することができ、達成するために特定の値を追加または削除します。

SmartInstantiationAwareBeanPostProcessor
3つのメソッドを提供していますプロセッサ、スマートビーンのインスタンス化。

predictBeanTypeの
postProcessBeforeInstantiationコールバックハンドラからの予測には、Beanの最終型を返します。

determineCandidateConstructorsは、
ビーンをインスタンス化するコンストラクタを使用して決定しました。

getEarlyBeanReference
早期暴露Bean参照を取得し、早期のエクスポージャー豆だけで、完成はまだビーンのプロパティの割り当てと初期化を完了していないインスタンス化されます。

MergedBeanDefinitionPostProcessor
postProcessMergedBeanDefinition
ビーン定義情報を合成後処理方法ビーンがインスタンス化した後、方法は、設定値の前に呼び出されます。

達成するための自動組立
自動組立に必要な要素を見つける
AutowiredAnnotationBeanPostProcessorポストプロセッサが追加@Autowiredと@value注釈要素の自動組立を実装するための主な責任があるが。だから、実際には、@Autowiredと@value注釈に解決、自動化されたアセンブリを必要とする要素を検索します。

AutowiredAnnotationBeanPostProcessor次のように自動実装要素の必要性を識別するために、ポストプロセッサが、この方法のMergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition呼び出しリンクで実現されます。

445を、AutowiredAnnotationBeanPostProcessor $ 2(org.springframework.beans.factory.annotation):doWith
doWithLocalFields:657、ReflectionUtils(org.springframework.util)
buildAutowiringMetadata:433、AutowiredAnnotationBeanPostProcessor(org.springframework.beans.factory.annotation)
findAutowiringMetadata:412、AutowiredAnnotationBeanPostProcessor (org.springframework.beans.factory.annotation)
postProcessMergedBeanDefinition:235、AutowiredAnnotationBeanPostProcessor(org.springframework.beans.factory.annotation)
applyMergedBeanDefinitionPostProcessors:1000、AbstractAutowireCapableBeanFactory(org.springframework.beans.factory.support)
doCreateBean:523、AbstractAutowireCapableBeanFactory(ORG .springframework.beans.factory.support)
たcreateBean:483、AbstractAutowireCapableBeanFactory(org.springframework.beans.factory.support)
のgetObject:312、AbstractBeanFactory $ -1(org.springframework.beans.factory.support)
getSingleton:230、DefaultSingletonBeanRegistry(org.springframework.beans.factory.support)
doGetBean :308、AbstractBeanFactory(org.springframework.beans.factory.support)
getBean:197、AbstractBeanFactory(org.springframework.beans.factory.support)
preInstantiateSingletons:761、DefaultListableBeanFactory(org.springframework.beans.factory.support)
finishBeanFactoryInitialization:867 、AbstractApplicationContext(org.springframework.context.support)
リフレッシュ:543、AbstractApplicationContext(org.springframework.context.support)
<init>:84、AnnotationConfigApplicationContext( org.springframework.context.annotation)
私たちは、リンクからご覧必要な自動組立がfindAutowiringMetadata方法で達成された要素を見つけることができ、この方法は、メタデータ情報を構築するためにbuildAutowiringMetadataの道を呼び出すことになります。注釈は、それがオブジェクトAutowiredFieldElement内にカプセル化される特性にロードされている場合、アノテーションをメソッドに適用された場合、要素はAutowiredMethodElementオブジェクトにカプセル化されます。この方法は、本明細書で2つのオブジェクトがプロパティ値を注入確定する噴射、主な違いは、反射注射値を使用することは同じではありませんです。ソースは以下のとおりです。

プライベートInjectionMetadata buildAutowiringMetadata(finalクラス<www.yongshenyul.com> clazz){
LinkedListの<InjectionMetadata.InjectedElement>要素=新しいLinkedListの<InjectionMetadata.InjectedElement>();
<?>クラスtargetClass = clazz。

{行う
//ストアメタデータ情報を、我々は発見
のLinkedList <InjectionMetadata.InjectedElement> = currElements最終
新しい新規のLinkedList <InjectionMetadata.InjectedElement>(www.yuanygw.com);

//すべてのクラスフィールドを反射することで、オブジェクトに対応する検索
ReflectionUtils.doWithLocalFields (targetClass、新しい新しいReflectionUtils.FieldCallback(){
@Override
公共ボイドdoWith(フィールド、フィールド)は、IllegalAccessExceptionが{IllegalArgumentExceptionをスローし
た場合、//はフィールド上の反射によってすべての注釈情報を検索し、そこ@Autowiredされているか否かを判断し、@value注釈オブジェクトAutowiredFieldElementのフィールドに封入
AnnotationAttributesアンfindAutowiredAnnotation =(フィールド);
(!アン= NULL){IF
IF(Modifier.isStatic(field.getModifiers())){
IF(logger.isWarnEnabled(www.baichuangyule.cn) ){
logger.warn(「注釈Autowiredがサポートされていないが、静的フィールド上にある:」フィールド+);
}
リターン;
}
ブール= determineRequiredStatusが必要(アン);、
// AutowiredFieldElementはキャッシュとにフィールドオブジェクトに封入
currElements.add (新しい新しいAutowiredFieldElement(フィールド、必須));
}
}
})。

//メソッドがクラスに対応するオブジェクトがすべての反射を識別するために
ReflectionUtils.doWithLocalMethods(www.jintianxuesha.com targetClass、新しい新しいReflectionUtils.MethodCallback(){
@Override
公共ボイドdoWith(方法メソッド)IllegalArgumentExceptionをスローし、IllegalAccessExceptionが{
メソッドbridgedMethod = www.yuchengyuledl BridgeMethodResolver.findBridgedMethod .COM(方法);
(!BridgeMethodResolver.isVisibilityBridgeMethodPair(方法、bridgedMethod)){IF
リターン;
}
フィールド上の反射によって//すべてのアノテーション情報を見つけるために、及び@Autowiredと@value注釈があるか否かを判定し、もしオブジェクトAutowiredMethodElementのフィールドに存在封止され
AnnotationAttributes =アンfindAutowiredAnnotation(bridgedMethod);
(!= NULL &&アンmethod.equals(ClassUtils.getMostSpecificMethod(方法、clazz)))IF {
IF(Modifier.isStatic(method.getModifiers() )){
IF(logger.isWarnEnabled()){
logger.warn( "Autowired注釈が静的メソッドはサポートされていません:" +メソッド);
}
を返します。
}
IF(。method.getParameterTypes()長さ== 0){
IF(logger.isWarnEnabled()){
logger.warn( "Autowired注釈のみパラメータを持つ方法で使用されるべきである:" +
メソッド);
}
}
ブール= determineRequiredStatus(アン)が必要。
PropertyDescriptorをPD = BeanUtils.findPropertyForMethod(bridgedMethod、clazz)。
//将该字段封成AutowiredMethodElement对象
currElements.add(新しいAutowiredMethodElement(方法、必須、PD))。
}
}
})。

elements.addAll(0、currElements);
targetClass targetClass.getSuperclass =();
}
//ループ処理要素は、親オートワイヤリング必要
しばらく(www.qjljdgt.cn targetClass = NULL && targetClass = Object.classを!!);
/ /要素は自動的にパッケージInjectionMetadataオブジェクト定義に組み立てられ、豆にマージされ
、新しい新しいInjectionMetadata(clazz、要素)を返す;
}
自動組立工程を必要見つけます。

クラスオブジェクトは、すべての反射によって得られ、 `` `Method````フィールドオブジェクトが
反射して、フィールドおよびメソッドにアノテーションを取得し、@Autowired @value注釈とが存在するか否かを判定する
フィールド@Autowiredと@valueの注釈は法とAutowiredFieldElement AutowiredMethodElementオブジェクトにカプセル化され、次回の自動組立を待ちます。
ループ処理は、自動組立の親要素を必要と
自動的にパッケージInjectionMetadataオブジェクトに要素を組み立て、最後に定義された属性externallyManagedConfigMembers Beanにマージされ
たプロパティ値注入
AutowiredAnnotationBeanPostProcessorポストプロセッサ噴射特性値がpostProcessPropertyValuesプロセスで達成されます。ソースは以下のとおりです。

注入し、ボイドパブリック(オブジェクトのターゲット、文字列のbeanName、PropertyValuesのPVS)がThrowableを{スロー
//(ここでは、それはバッファを取られる)メタデータ情報が自動的に嵌合する取得
コレクション<InjectedElement> elementsToIterate =
(this.checkedElements!= nullの?this.checkedElements :this.injectedElements);
IF){(elementsToIterate.isEmpty(www.jinyazptdL.cn)!
ブールlogger.isDebugEnabledデバッグ=();
(InjectedElement要素について:elementsToIterate){
IF(デバッグ){
logger.debug(「処理が注入豆要素' "+のbeanName +"'の:「エレメント+);
}
// AutowiredFieldElementメソッドを呼び出す注入または射出AutowiredMethodElementオブジェクト属性値
element.inject(ターゲットのbeanName、PVS) 。
}
}
}
AutowiredFieldElement#1噴射
@Override
保護されたボイド注入(オブジェクト・ビーン、文字列のbeanName、PropertyValuesのPVS)がThrowableを{スロー
フィールドフィールド=(フィールド)をthis.member。
オブジェクトの値。
IF(this.cached){
値= resolvedCachedArgument(のbeanName、this.cachedFieldValue)。
}
他{
DependencyDescriptorのDESC =新しいDependencyDescriptor(フィールド、this.required)。
desc.setContainingClass(bean.getClass())。
設定して<文字列> autowiredBeanNames =新しいLinkedHashSetの<文字列>(1);
TypeConverterのTypeConverter = beanFactory.getTypeConverter()。
試す{
//在容器中获取需要装配的ビーン
値= beanFactory.resolveDependency(DESC、のbeanName、autowiredBeanNames、にTypeConverter)。
}
...
}
{(値!= NULL)場合
//通过反射设置属性值
ReflectionUtils.makeAccessible(フィールド);
field.set(豆、値)。
}
}
AutowiredMethodElement#注入
@Overrideは
空隙注入を保護された(オブジェクト・ビーン、文字列のbeanName、PropertyValuesのPVS)スローのThrowable {
IF(checkPropertySkipping(PVS)){
返します。
}
メソッドのメソッド=(方法)this.member。
オブジェクト[]引数。
もし(this.cached){
//同期を回避するためのショートカット...
引数=のresolveCachedArguments(のbeanName)。
}
他{
<?>クラス[] paramTypes = method.getParameterTypes()。
引数=新しいオブジェクト[paramTypes.length]。
DependencyDescriptor []記述子=新しいDependencyDescriptor [paramTypes.length]。
設定して<文字列> autowiredBeans =新しいLinkedHashSetの<文字列>(paramTypes.length)。
TypeConverterのTypeConverter = beanFactory.getTypeConverter()。
以下のために(INT i = 0; I <arguments.lengthを、iは++){
MethodParameter methodParam =新しいMethodParameterを(方法I)。
DependencyDescriptor currDesc =新しいDependencyDescriptor(methodParam、this.required)。
currDesc.setContainingClass(bean.getClass())。
記述子[I] = currDesc。
試す{
//在容器中获取需要装配的ビーン
オブジェクトのarg = beanFactory.resolveDependency(currDesc、のbeanName、autowiredBeans、にTypeConverter)。
場合(!argが== nullの&& this.required){
引数= NULL;
ブレーク;
}
;引数は、[I]はアルギニン=
}
{キャッチ(BeansException EX)を
投げ、新たな新UnsatisfiedDependencyException(ヌル、のbeanName、新しい新InjectionPoint(methodParam)、EX);
}
}
...
}
IF(!= NULLの引数){
試み{
//反映メソッドを呼び出すことによって設定された要素の値
ReflectionUtils.makeAccessible(メソッド)を、
Method.invoke(豆、引数);
}
...
}
}
ここから我々は、ソースとAutowiredMethodElement AutowiredFieldElement完全自動アセンブリは、外出先のコンテナを探している見ることができます次に、取得した対象物体によって反射された対応するBeanは、自動組立を完了BeanにBeanの配置しました。

まとめ
私たちは春の豆自動組立プロセスは見ることができます:

すべてのフィールドとメソッド情報の反射によって取得されたクラスオブジェクト、
自動的に組み立てることが必要であるかどうか、アノテーション情報のフィールドと取得方法、および注釈の種類による反射を介して
要素が自動的に組み立てされ、包装さAutowiredFieldElementとAutowiredMethodElementオブジェクト
AutowiredFieldElementとAutowiredMethodElementを呼び出し注入方法は次の工程を呼び起こす
容器()メソッドを呼び出すビーンgetBeanによって注入されるソース・データを見つけるために
ターゲットにBeanのビーン見出さ反射ソースデータ
自動組立工程において問題が周期依存関心を伴います春は、この記事のソースを見ることができます(8)円形の依存関係

おすすめ

転載: www.cnblogs.com/dakunqq/p/11616879.html