[春のソースコード:FactoryBean 2]最後に、FactoryBeanがBean作成プロセスをカスタマイズする方法を理解します

前書き

では前の記事、私たちは分析に焦点を当てた流れgetObjectTypeの中にメソッドFactoryBeanのをそして最終的には一般的なフローチャートを描いた、我々は(IOrderService.calss)に渡されたクラス型との関係を説明し、私たちのカスタムFactoryBeanのサブクラス接続方法、つまりgetBean(IOrderService.class)を呼び出すと、最下層は最終的にfactoryBean.getObjectType()を呼び出します

この記事では、FactoryBeanがSpringコンテナでgetObject()を呼び出して生成されたBeanを管理する方法を分析、次に前の記事のフォローアップ分析(以下に示す)を行います。

DefaultListableBeanFactory#resolveNamedBean

現時点では、いくつかの変数値は次のとおりです:

  • requiredType:IOrderService.class
  • 候補者名:{“ orderFactoryBean”}

CandidateNames配列の長さが1であるため、getBean(beanName、requiredType、args)メソッドに入ります。このメソッドはdoGetBeanメソッドを呼び出します。doGetBeanはSpringコンテナーの初期化の非常に重要な部分ですが、ここではあまり多くのSpringBeanの寿命を分析しません。サイクルの内容は、この記事ではFactoryBeanに関連する内容のみに焦点を当てています。

AbstractBeanFactory#doGetBean (一部の無関係なコードは省略)

	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

        //转换传入的BeanName的值,如&name变为name 以及别名(alias)的转换
		final String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
        //调用getSingleton方法 从Spring容器中获取单例Bean,下面再具体分析此方法
        //这里的beanName为orderFactoryBean,获取到的是它对应的OrderFactoryBean实例(因为我们有添加@Component注解,spring容器中已创建该bean)
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {

            //这里是根据获取到的OrderFactoryBean实例本身去获取对象
            //注意这里传入了name和转换后的beanName
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

 DefaultSingletonBeanRegistry#getSingleton 、SpringコンテナからシングルトンBeanを取得します

	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //先从singletonObjects单例池(一级缓存)中获取Bean,singletonObjects是一个ConcurrentHashMap
        //key是beanName value是单例Bean		
        Object singletonObject = this.singletonObjects.get(beanName);
		//如果单例池中不存在,并且是当前正在创建中的Bean
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            // 加锁
			synchronized (this.singletonObjects) {
                //从二级缓存中获取早期的bean
				singletonObject = this.earlySingletonObjects.get(beanName);
                //如果没有获取到,并且允许提前引用相应的Bean(依赖注入)
				if (singletonObject == null && allowEarlyReference) {
                    //singletonFactories俗称三级缓存,key:beanName,value:ObjectFactory
                    // 这个ObjectFactory是一个函数式接口,所以支持Lambda表达式:() -> getEarlyBeanReference(beanName, mbd, bean)
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
                        //从ObjectFactory中获取Bean实例
						singletonObject = singletonFactory.getObject();
                        //放入earlySingletonObjects这个Map二级缓存中,依赖注入时用到
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

この方法は非常に重要であり、Springコンテナの3レベルのキャッシュが含まれます。

  • レベル1キャッシュsingletonObjects。完全なライフサイクルを経たBeanオブジェクトキャッシュします。
  • 第2レベルのキャッシュsingletonObjectsより1つ早いearlySingletonObjects、キャッシュされたBeanオブジェクトが初期のBeanオブジェクトであることを示します(またはキャッシュがAOP元のオブジェクト事前に取得した後に取得されたプロキシオブジェクト)。アーリーとはどういう意味ですか?BeanがearlySingletonObjectsに配置される前に、Beanのライフサイクルが完了していないことを示します。
  • 3レベルのキャッシュsingletonFactories キャッシュはObjectFactoryであり、オブジェクトの作成に使用されるオブジェクトファクトリを表します。

第2レベルのキャッシュは、主にSpringの循環依存関係を解決するために使用されます。SingletonFactoriesは、主に元のオブジェクトとAOP後に取得されたプロキシオブジェクトを生成するために使用されます。詳細については、「[インタビューの質問]最後に誰かがSpringの循環依存関係を明確に説明できます。 "、よく書かれています。

以下のトピックに戻り、AbstractBeanFactory#  getObjectForBeanInstanceを分析してみましょう。

	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

        // 如果传进来的OrderFactoryBean不属于FactoryBean的实例,则直接返回当前实例(表示它是普通的bean)
		if (!(beanInstance instanceof FactoryBean)) {
			return beanInstance;
		}
        
        // 如果是FactoryBean子类bean
		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		else {// 缓存中获取
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// Return bean instance from factory.
            //如果能走到这里来,说明这个bean实例是FactoryBean类型的
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton.
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
            // 从该方法名字看出:从FactoryBean中获取对象,下面再具体分析
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

分析FactoryBeanRegistrySupport# getObjectFromFactoryBean

	protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {

        //FactoryBean类型的实例是否单例
		if (factory.isSingleton() && containsSingleton(beanName)) {
			synchronized (getSingletonMutex()) {
                //从缓存中获取
				Object object = this.factoryBeanObjectCache.get(beanName);
				if (object == null) {

                    //缓存获取不到,则调用doGetObjectFromFactoryBean方法从FactoryBean中获取bean对象
                    //这里是调用的FactoryBean的getObject方法来获取的,具体看这一步
					object = doGetObjectFromFactoryBean(factory, beanName);
					// Only post-process and store if not put there already during getObject() call above
					// (e.g. because of circular reference processing triggered by custom getBean calls)
                    //再从缓存中获取一次
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);

                    //如果上一步的缓存中获取到了,则用缓存中的替代FactoryBean中获取的bean
					if (alreadyThere != null) {
						object = alreadyThere;
					}
					else {
						if (shouldPostProcess) {
							if (isSingletonCurrentlyInCreation(beanName)) {
								// Temporarily return non-post-processed object, not storing it yet..
								return object;
							}
							beforeSingletonCreation(beanName);
							try {
                                //调用BeanPostProcessor中的postProcessAfterInitialization方法进行处理
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							catch (Throwable ex) {
								throw new BeanCreationException(beanName,
										"Post-processing of FactoryBean's singleton object failed", ex);
							}
							finally {
								afterSingletonCreation(beanName);
							}
						}
						if (containsSingleton(beanName)) {
                            //添加到factoryBeanObjectCache中缓存,key为beanName
							this.factoryBeanObjectCache.put(beanName, object);
						}
					}
				}
				return object;
			}
		}
		else {
            //FactoryBean的实例非单例情况
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			if (shouldPostProcess) {
				try {
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
				}
			}
			return object;
		}
	}

doGetObjectFromFactoryBeanを分析します。これは、オブジェクトを取得するために呼び出されるFactoryBeanのgetObjectメソッドです。

	private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
			throws BeanCreationException {

		Object object;
		try {
			if (System.getSecurityManager() != null) {
				AccessControlContext acc = getAccessControlContext();
				try {
					object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
                // 终于看到了FactoryBean中的getObject(),真相大白
				object = factory.getObject();
			}
		}

		return object;
	}

大まかなフローチャート(引用

総括する

大まかなプロセス:渡したクラスタイプに従って、Springコンテナ内のすべてのBeanNameをループし、beanNameに従って対応するBeanインスタンスを取得し、取得したBeanインスタンスがFactoryBeanタイプのBeanであるかどうかを判断します。そうである場合は、FactoyBeanのgetObjectTypeメソッドを呼び出します。クラスを取得し、取得したクラスを渡されたクラスと照合します。一致する場合は、このbeanNameと渡されたクラスの間にマッピング関係を確立します。次に、beanNameに従ってSpringコンテナ内の対応するFactoryBeanインスタンスBeanを取得し、FactoryBeanのgetObjectメソッドを呼び出して、メソッド内のカスタムBeanを取得します。

参照:https//conan.blog.csdn.net/article/details/79588391

史上最強のTomcat8パフォーマンス最適化

なぜアリババは90秒で100億に抵抗できるのですか?-サーバー側の高同時分散アーキテクチャの進化

B2Beコマースプラットフォーム--ChinaPayUnionPay電子決済機能

Zookeeperの分散ロックを学び、インタビュアーに感心してあなたを見てもらいましょう

SpringCloudeコマーススパイクマイクロサービス-Redisson分散ロックソリューション

もっと良い記事をチェックして、公式アカウントを入力してください-私にお願いします-過去に素晴らしい

深くソウルフルなパブリックアカウント0.0

おすすめ

転載: blog.csdn.net/a1036645146/article/details/111736852