[Código fuente de Spring: FactoryBean II] Finalmente, comprenda cómo FactoryBean personaliza el proceso de creación de beans

Introducción

En el artículo anterior , nos enfocamos en analizar el flujo del método getObjectType en FactoryBean , y finalmente dibujamos un diagrama de flujo general, describiendo la relación entre el tipo de clase que pasamos (IOrderService.calss) y nuestra subclase FactoryBean personalizada Cómo conectarse, es decir, llamamos a getBean (IOrderService.class) , y la capa inferior eventualmente llamará a factoryBean.getObjectType () .

En este artículo, analizaremos cómo FactoryBean permite que el contenedor Spring administre los beans generados llamando a su getObject () , y luego el análisis de seguimiento del artículo anterior (como se muestra a continuación):

DefaultListableBeanFactory # resolveNamedBean

En este momento, algunos de los valores de las variables son los siguientes:

  • requiredType: IOrderService.class
  • candidatoNames: {"orderFactoryBean"}

Debido a que la longitud de la matriz candidateNames es 1, que entrará en la getBean (beanName, requiredType, args) método, este método llama al doGetBean método, doGetBean es una parte muy importante de la inicialización del contenedor primavera, pero aquí no va a analizar demasiado la vida de beans Spring El contenido del ciclo, sólo nos centramos en el contenido relacionado con FactoryBean en este artículo.

AbstractBeanFactory # doGetBean  (se omite algún código irrelevante)

	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 , obtenga el bean singleton del contenedor Spring

	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;
	}

Este método es muy importante e involucra la caché de tres niveles en el contenedor Spring:

  • Caché de nivel 1 : singletonObjects , objetos bean almacenados en caché que han pasado por un ciclo de vida completo.
  • Caché de segundo nivel : earlySingletonObjects , uno más temprano que singletonObjects, indica que el objeto bean en caché es el objeto bean temprano (o: el objeto proxy obtenido después de que la caché toma el objeto original para AOP por adelantado ). ¿Qué significa temprano? Indica que el ciclo de vida del Bean no se ha completado antes de que el Bean se coloque en earlySingletonObjects.
  • Caché de tres niveles : singletonFactories , el caché es ObjectFactory, que representa una fábrica de objetos, que se utiliza para crear un objeto.

El caché de segundo nivel se usa principalmente para resolver la dependencia circular en Spring. SingletonFactories se usa principalmente para generar el objeto original y el objeto proxy obtenido después de AOP. Para obtener más detalles, consulte "[Pregunta de la entrevista] Finalmente, alguien puede explicar la dependencia circular de Spring claramente " , bien escrito.

Volvamos al tema siguiente y luego analicemos AbstractBeanFactorygetObjectForBeanInstance

	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;
		}
	}

Analice doGetObjectFromFactoryBean , aquí está el método getObject de FactoryBean llamado para obtener el objeto

	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;
	}

Diagrama de flujo aproximado ( citado )

para resumir

Proceso aproximado : de acuerdo con el tipo de clase que pasamos, repita todos los BeanNames en el contenedor Spring, y luego obtenga la instancia de Bean correspondiente de acuerdo con el beanName, y determine si la instancia de Bean obtenida es un Bean del tipo FactoryBean; si lo es, llame al método getObjectType de FactoyBean Obtenga la clase y haga coincidir la clase obtenida con la clase pasada; si coincide, establezca una relación de mapeo entre este beanName y la clase pasada. Luego, obtenga el bean de instancia de FactoryBean correspondiente en el contenedor Spring de acuerdo con el beanName y llame al método getObject de FactoryBean para obtener el bean personalizado en nuestro método.

Referencia: https://conan.blog.csdn.net/article/details/79588391

● La optimización de rendimiento de Tomcat8 más sólida de la historia

¿Por qué Alibaba puede resistir 10 mil millones en 90 segundos? - La evolución de la arquitectura distribuida de alta concurrencia del lado del servidor

Plataforma de comercio electrónico B2B: función de pago electrónico ChinaPay UnionPay

Aprenda el candado distribuido de Zookeeper, deje que los entrevistadores lo miren con admiración

Solución de bloqueo distribuido de Redisson con microservicio de pico de comercio electrónico de SpringCloud

Vea más artículos buenos, ingrese a la cuenta oficial, por favor, excelente en el pasado

Una cuenta pública profunda y conmovedora 0.0

Supongo que te gusta

Origin blog.csdn.net/a1036645146/article/details/111736852
Recomendado
Clasificación