引数はinstantiateBeanをインスタンス化しないと二十から四getBeanは10コンストラクタを詳細春5.xのソース旅

デフォルトコンストラクタを呼び出すinstantiateBean

以前は普通のインスタンスが作成されている場合、それが唯一のデフォルトコンストラクタは、デフォルトコンストラクタを行う方法で見てみましょうすることができ、おそらく多く、そこにオーバーロードされ、使用することができますコンストラクタを探します、と述べました彼は比較的簡単ですので。
実際には、そこにインスタンス化戦略を取得することで、その後、instantiateインスタンス化、言った戦略の前でCglibSubclassingInstantiationStrategyはなく、一般的または親と、注射した場合にのみ作業を意志SimpleInstantiationStrategyさんinstantiate

	protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
		try {
			Object beanInstance;
			final BeanFactory parent = this;
			if (System.getSecurityManager() != null) {
				beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
						getInstantiationStrategy().instantiate(mbd, beanName, parent),
						getAccessControlContext());
			}
			else {
				beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
			}
			BeanWrapper bw = new BeanWrapperImpl(beanInstance);//包装成BeanWrapper
			initBeanWrapper(bw);
			return bw;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
		}
	}

SimpleInstantiationStrategy的インスタンス化

メソッドをオーバーロードされたことが判明した場合は、必要なCGLIBインスタンスを直接にデフォルトコンストラクタを取得していない場合は、動的エージェントに。すでに述べたようにインスタンス化そしてので、ここであなたが彼の直接施工方法を得ることができ、引数なしのコンストラクタであることが判明し、されています。

@Override
	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
		// Don't override the class with CGLIB if no overrides.
		if (!bd.hasMethodOverrides()) {//无lookup重载的方法
			Constructor<?> constructorToUse;
			synchronized (bd.constructorArgumentLock) {
				constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse == null) {
					final Class<?> clazz = bd.getBeanClass();
					if (clazz.isInterface()) {
						throw new BeanInstantiationException(clazz, "Specified class is an interface");
					}
					try {
						if (System.getSecurityManager() != null) {
							constructorToUse = AccessController.doPrivileged(
									(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
						}
						else {
							constructorToUse = clazz.getDeclaredConstructor();
						}
						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
					}
					catch (Throwable ex) {
						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
					}
				}
			}
			return BeanUtils.instantiateClass(constructorToUse);
		}
		else {//有lookup重载的话要用CGLIB动态代理了
			// Must generate CGLIB subclass.
			return instantiateWithMethodInjection(bd, beanName, owner);
		}
	}

々BeanUtils的instantiateClass

ここでは、コンストラクタを呼び出す例ですが、見てみましょうことはないがKotlin、そして一般的であり、JAVA作成したインスタンス化するコンストラクタメソッド。

public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
		Assert.notNull(ctor, "Constructor must not be null");
		try {
			ReflectionUtils.makeAccessible(ctor);
			if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
				return KotlinDelegate.instantiateClass(ctor, args);
			}
			else {
				Class<?>[] parameterTypes = ctor.getParameterTypes();
				Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters");
				Object[] argsWithDefaultValues = new Object[args.length];
				for (int i = 0 ; i < args.length; i++) {//获得参数
					if (args[i] == null) {
						Class<?> parameterType = parameterTypes[i];
						argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);
					}
					else {
						argsWithDefaultValues[i] = args[i];
					}
				}
				return ctor.newInstance(argsWithDefaultValues);
			}
		}
		catch (InstantiationException ex) {
			throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
		}
		catch (IllegalAccessException ex) {
			throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
		}
		catch (IllegalArgumentException ex) {
			throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
		}
		catch (InvocationTargetException ex) {
			throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());
		}
	}

CglibSubclassingInstantiationStrategy的instantiateWithMethodInjection

あなたが発見した場合はloolupアノテーション付きメソッドを、それがこのメソッドを呼び出します。

	@Override
	protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
		return instantiateWithMethodInjection(bd, beanName, owner, null);
	}
	
	@Override
	protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
			@Nullable Constructor<?> ctor, Object... args) {

		// Must generate CGLIB subclass...
		return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);
	}

CglibSubclassCreator的インスタンス化

まず作成GCLIBブースターサブクラスを、コンストラクタに渡された場合は空ですが、私はちょうど使用BeanUtilsすることGCLIBそれ以外の場合は、コンストラクタサブクラスは、インスタンスを直接強化、サブクラスをインスタンス化。そして、メソッドのインターセプタを設定し、その呼び出しはあなたが容器の検索に行くことができ迎撃に入ると、作成されていない、直接のリターンがあります。

public Object instantiate(@Nullable Constructor<?> ctor, Object... args) {
			Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
			Object instance;
			if (ctor == null) {
				instance = BeanUtils.instantiateClass(subclass);
			}
			else {
				try {
					Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
					instance = enhancedSubclassConstructor.newInstance(args);
				}
				catch (Exception ex) {
					throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
							"Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);
				}
			}
			// SPR-10785: set callbacks directly on the instance instead of in the
			// enhanced class (via the Enhancer) in order to avoid memory leaks.
			Factory factory = (Factory) instance;
			factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
					new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
					new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
			return instance;
		}

ノートの戦闘LOOKUP

時には、あなたはとても実装クラスは、このような、依存していることを、実際には、実装クラスに依存して、インスタンス化のBeanへの書き込みノートに同じファイルを書きたくないことがあります。
ここに画像を挿入説明
しかし、我々はデカップリングする方法を考えますが、このことができクラスが依存するだろうspringなどと、あなたは他のフレームワークと独立して与えたい場合は、それはそうと推定されること、そしてまだ彼の方法を考える必要がないことxml、またはカスタムポストプロセッサ。
ここに画像を挿入説明
ここに画像を挿入説明
これは、その後、問題を切り離す時間の実装:インターセプタは入って来、あなたが最後に呼び出すことで見ることができますあなたが望むタイプを渡して、これは最後の内部には、中に封入し、戻り、その後、あなたはあなたを削除することができますオブジェクトは、もちろん、まだそこに呼んでいるべき取得します。我々は、単一の例のコンテナことがわかります。
ここに画像を挿入説明
LookupOverrideMethodInterceptorowner.getBeanUserDao
ここに画像を挿入説明
ここに画像を挿入説明
NamedBeanHoldergetBeanInstancegetBean
ここに画像を挿入説明

注意点

同じタイプの2つの例は存在しない、または他の名前を指定するか、または例外を報告しない限り、彼は知っている、あなたが望むものではありませんありません。
ここに画像を挿入説明

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.ww.pojo.UserDao' available: expected single matching bean but found 2: testBean,userDao

あなたは、この名前を追加することができます。
ここに画像を挿入説明
または、このように:
ここに画像を挿入説明

さて、今日ここに、私たちは自分自身の学習、限られた容量を理解し、偉大な神は見スプレーしないで、言い訳してください、助けの調査に希望と理解しています。

公開された235元の記事 ウォン称賛74 ビュー30000 +

おすすめ

転載: blog.csdn.net/wangwei19871103/article/details/105115447