Proceso de carga de frijoles de Spring

El contenedor Spring IOC es como una máquina en una línea de ensamblaje que produce productos, y los granos creados por Spring son como productos exquisitos producidos al final de la línea de ensamblaje. Dado que es una máquina, debe iniciarse primero, y Spring no es una excepción. Por lo tanto, el proceso de carga de Bean se puede dividir en dos etapas en general:

  • Fase de inicio del contenedor
  • Fase de creación de frijoles

1. Fase de puesta en marcha del contenedor:

Se ha realizado una gran cantidad de trabajo de calentamiento durante la fase de inicio del contenedor, que está completamente preparado para la instanciación posterior de Bean. Veamos primero qué trabajo de calentamiento se ha realizado durante la fase de inicio del contenedor.

1. Meta información de configuración:

El contenedor Spring IOC separa la creación de instancias de objetos del uso de instancias de objetos. Cuando la empresa necesita depender de un objeto, ya no dependemos de nosotros para crearlo manualmente. Solo pregúntele a Spring, y Spring nos dará lo que necesitamos. por inyección Objeto dependiente. Ahora que la tarea de creación de objetos se transfiere a Spring, Spring necesita conocer la información necesaria para crear un objeto. Y esta información necesaria puede ser el archivo de configuración xml más completo que Spring admite en el pasado, u otras formas de archivos de disco, como propiedades, también pueden ser anotaciones convencionales o incluso codificación directa de código. En resumen, la información necesaria para crear un objeto se denomina metainformación de configuración.

<bean id="role" class="com.wbg.springxmlbean.entity.Role">
    <!-- property元素是定义类的属性,name属性定义的是属性名称 value是值
    相当于:
    Role role=new Role();
    role.setId(1);
    role.setRoleName("高级工程师");
    role.setNote("重要人员");-->
    <property name="id" value="1"/>
    <property name="roleName" value="高级工程师"/>
    <property name="note" value="重要人员"/>
</bean>

2 、 BeanDefination:

En el mundo de Java, todo es un objeto. Las anotaciones esparcidas por el código del programa y la meta información de configuración como xml u otros archivos guardados en el disco siempre deben estar representados en forma de objeto en la memoria, al igual que nosotros. La persona correspondiente al mundo Java es una clase Person, y Spring elige representar esta metainformación de configuración en memoria es BeanDefination, aquí no analizaremos el código de BeanDefination, aquí solo necesitamos saber que la metainformación de configuración es cargado en la memoria Entonces puede existir en forma de BeanDefination.

3 、 BeanDefinationReader:

¿Cómo entiende Spring esta metainformación de configuración? Esto depende de nuestro BeanDefinationReader. Diferentes BeanDefinationReader tienen diferentes funciones, si queremos leer la metainformación de configuración xml, entonces podemos usar XmlBeanDefinationReader. Si queremos leer el archivo de configuración de propiedades, podemos usar PropertiesBeanDefinitionReader para cargarlo. Y si queremos leer la metainformación de la configuración de anotaciones, podemos usar AnnotatedBeanDefinitionReader para cargar. También podemos personalizar fácilmente BeanDefinationReader para controlar la carga de metainformación de configuración. En general, la función de BeanDefinationReader es cargar metainformación de configuración y convertirla en una forma de memoria de BeanDefination , que existe en un lugar determinado. En cuanto a dónde está este lugar, no te preocupes, ¡mira hacia abajo!

4 、 BeanDefinationRegistry:

En este punto de la ejecución, Spring ha cargado la metainformación de configuración que existe en todas partes en la memoria y la ha convertido en la forma de BeanDefination, de modo que cuando necesitemos crear una instancia de objeto, podamos encontrar la BeanDefination correspondiente y crear el objeto. Entonces, cuando necesitamos un objeto, ¿dónde encontramos la BeanDefination correspondiente? ¿Cómo se guardará la relación correspondiente o la relación de mapeo de BeanDefination del objeto encontrado a través de la identificación definida por Bean? Esto conduce al BeanDefinationRegistry.

Después de que la información de configuración de Spring by BeanDefinationReader se cargue en el elemento de memoria generado correspondiente BeanDefination, que se registrará en BeanDefinationRegistry, BeanDefinationRegistry es una gran canasta de almacenamiento BeanDefination, también es un par clave-valor, según lo definido por un ID de Bean específico, asignado a la BeanDefination correspondiente.

5, BeanFactoryPostProcessor:

BeanFactoryPostProcessor es un punto de extensión proporcionado por Spring en la fase de inicio del contenedor, que es el principal responsable de modificar y reemplazar cada BeanDefination registrado en BeanDefinationRegistry hasta cierto punto. Por ejemplo, alguna información de configuración que puede ser modificada en nuestra metainformación de configuración se encuentra dispersa por todas partes, lo cual no es lo suficientemente flexible, y es problemático modificar la configuración correspondiente, en este momento podemos usar marcadores de posición para configurar. Por ejemplo, al configurar la conexión DataSource de Jdbc, puede configurarlo así:

<bean id="dataSource"  
    class="org.apache.commons.dbcp.BasicDataSource"  
    destroy-method="close">  
    <property name="maxIdle" value="${jdbc.maxIdle}"></property>  
    <property name="maxActive" value="${jdbc.maxActive}"></property>  
    <property name="maxWait" value="${jdbc.maxWait}"></property>  
    <property name="minIdle" value="${jdbc.minIdle}"></property>  
  
    <property name="driverClassName"  
        value="${jdbc.driverClassName}">  
    </property>  
    <property name="url" value="${jdbc.url}"></property>  
  
    <property name="username" value="${jdbc.username}"></property>  
    <property name="password" value="${jdbc.password}"></property>  
</bean> 

El BeanFactoryPostProcessor hará la modificación final al BeanDefination registrado en el BeanDefinationRegistry, reemplazando el marcador de posición $ con los datos reales en el archivo de configuración.

En este punto, incluso si se completa toda la fase de inicio del contenedor, el producto final de la fase de inicio del contenedor es el BeanDefination registrado en BeanDefinationRegistry Este es el trabajo de precalentamiento realizado por Spring para la instanciación de Bean. Repasemos lo que sucedió durante la fase de inicio del contenedor en forma de imagen.

 

 

2. Fase de adquisición de frijoles:

En la fase de inicio del contenedor, se completó el registro del bean. Si el objeto está configurado para cargarse de forma diferida, existirá en la forma de BeanDefination en BeanDefinationRegistry hasta que dependamos de la instancia del objeto en Spring, es decir, Spring solo existe cuando confiamos en el objeto por primera vez. Solo entonces comenzar la fase de instanciación del objeto correspondiente. Y si no elegimos la carga diferida, después de que se complete la fase de inicio del contenedor, hay un paso finishBeanFactoryInitialization (), que iniciará inmediatamente la fase de instanciación de Bean, e instanciará todo al llamar implícitamente al método getBean de todos los objetos dependientes El Bean configurado completa la carga de la clase.

1. doGetBean (): obtener bean:

La función general de doGetBean () es verificar si el bean existe en la caché o beanFactory antes de crear el objeto bean. Si existe, regresará. Si no existe, se llevará a cabo el proceso de creación correspondiente. Primero busquemos la entrada del método doGetBean () y leamos el código fuente de este método:

Primero llame a ApplicationContext.getBean ("beanName") para obtener el objeto Bean:

applicationContext.getBean("name");

Luego llame a AbstractApplicationContext.getBean ("beanName"):

    public Object getBean(String name) throws BeansException {
        assertBeanFactoryActive(); 
        // 调用getBean 进入AbstractBeanFactory    
        return getBeanFactory().getBean(name);
    }

Luego llame al método doGetBean () de la clase AbstractBeanFactory:

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

        /*
        1、转换beanName(别名转换):传入的参数name可能只是别名,也可能是FactoryBean,所以需要进行解析转换:
        (1)消除修饰符,比如工厂引用前缀 String FACTORY_BEAN_PREFIX = "&";
        (2)解决spring中alias标签的别名问题
        */ 
		final String beanName = transformedBeanName(name);
		Object bean;

        //2、尝试从缓存中去加载实例,如果获取到了就直接返回
		// Eagerly check singleton cache for manually registered singletons.
		Object sharedInstance = getSingleton(beanName);
		//如果缓存中存在对应的bean
		if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			
			//3、缓存渠道的bean的实例化。从缓存中获取的bean是原始状态的bean,需要在这里对bean进行bean实例化。
			// 此时会进行 合并RootBeanDefinition、BeanPostProcessor进行实例前置处理、实例化、实例后置处理。
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
        // 如果缓存中没有对应bean
		else { 
		    //4、循环依赖检查。 (构造器的循环依赖)循环依赖存在,则报错。
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

            // 5、如果缓存中没有数据,就会转到父类工厂去加载
            //获取父工厂
			// Check if bean definition exists in this factory.
			BeanFactory parentBeanFactory = getParentBeanFactory();
			
            //!containsBeanDefinition(beanName)就是检测如果当前加载的xml配置文件中不包含beanName所对应的配置,就只能到parentBeanFacotory去尝试加载bean。
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}

			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

            //6、存储XML配置文件的GernericBeanDefinition转换成RootBeanDefinition,即为合并父类定义。
			try {
                // XML配置文件中读取到的bean信息是存储在GernericBeanDefinition中的,但Bean的后续处理是针对于RootBeanDefinition的,所以需要转换后才能进行后续操作。
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				//7、初始化依赖的bean
				String[] dependsOn = mbd.getDependsOn();
				//bean中可能依赖了其他bean属性,在初始化bean之前会先初始化这个bean所依赖的bean属性。
				if (dependsOn != null) {
					for (String dependsOnBean : dependsOn) {
						if (isDependent(beanName, dependsOnBean)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
						}
						registerDependentBean(dependsOnBean, beanName);
						getBean(dependsOnBean);
					}
				}

                //8、创建bean
				// Create bean instance.
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							try {
								return createBean(beanName, mbd, args);
							}
							catch (BeansException ex) {
								// Explicitly remove instance from singleton cache: It might have been put there
								// eagerly by the creation process, to allow for circular reference resolution.
								// Also remove any beans that received a temporary reference to the bean.
								destroySingleton(beanName);
								throw ex;
							}
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
					String scopeName = mbd.getScope();
					final Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
							@Override
							public Object getObject() throws BeansException {
								beforePrototypeCreation(beanName);
								try {
									return createBean(beanName, mbd, args);
								}
								finally {
									afterPrototypeCreation(beanName);
								}
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						throw new BeanCreationException(beanName,
								"Scope '" + scopeName + "' is not active for the current thread; consider " +
								"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
								ex);
					}
				}
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

		// Check if required type matches the type of the actual bean instance.
		if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
			try {
				return getTypeConverter().convertIfNecessary(bean, requiredType);
			}
			catch (TypeMismatchException ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("Failed to convert bean '" + name + "' to required type [" +
							ClassUtils.getQualifiedName(requiredType) + "]", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}

2. Obtenga el bean singleton de la caché: getSingleton (String beanName, boolean allowEarlyReference)

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	// 从缓存池中获取bean:singletonObjects 一级缓
    Object singletonObject = this.singletonObjects.get(beanName);
	
    // 如果一级缓存中为null,再判断是否正在创建
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		// 加锁,防止并发创建
		synchronized (this.singletonObjects) {
			// 从二级缓存中获取bean,如果此 bean 正在加载则不处理
			singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
				// 当某些方法需要提前初始化,调用 addSingletonFactory 方法将对应的objectFactory 初始化策略存储在 singletonFactories
				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
					singletonObject = singletonFactory.getObject();
					this.earlySingletonObjects.put(beanName, singletonObject);
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
	return singletonObject;
}

En Spring, los beans son singletons por defecto, y el singleton del mismo contenedor solo se creará una vez. Cuando el bean se obtiene posteriormente, se obtiene directamente de la caché singletonObjects singleton. Y debido a que la caché singleton es una variable pública, cuando se opera, se realiza una operación de bloqueo, lo que evita la operación de sobrescritura de la modificación o lectura simultánea de varios subprocesos.

También hay una variable earlySingletonObjects, que también es una caché de singleton, y también se usa para almacenar la relación entre beanName y la creación de la instancia de bean. A diferencia de singletonFactories, cuando un bean singleton se coloca en la caché singleton inicial, debe eliminarse de singletonFactories.Los dos son mutuamente excluyentes y se utilizan principalmente para resolver el problema de las dependencias circulares.

3. Obtenga el objeto de la instancia de Bean: getObjectForBeanInstance ()

En el método getBean (), getObjectForBeanInstance () es un método de alta frecuencia, este método aparece ya sea para obtener el bean en la caché singleton o para cargar el bean según diferentes estrategias de alcance. Debido a que el bean obtenido de la memoria caché es el bean en el estado original, es necesario crear una instancia del bean aquí.

get_object_from_factory_bean

Resumen del flujo del método:

  • (1) Verifique el tipo de bean: determine si es un bean de fábrica
  • (2) Sin procesamiento para no FactoryBean
  • (3) Procesando FactoryBean: Si es un tipo FactoryBean, primero convierta el bean y luego delegue al método getObjectFromFactoryBean () para su procesamiento.

En este método, hay un tratamiento especial para el bean de fábrica, y finalmente se obtiene el tipo devuelto por el método FactoryBean.getObject ().

4, 获 康 Ejemplo: getSingleton (String beanName, ObjectFactory <?> SingletonFactory)

// Create bean instance. 创建 bean 实例
// singleton 单例模式(最常使用)
if (mbd.isSingleton()) {
    // 第二个参数的回调接口,接口是 org.springframework.beans.factory.ObjectFactory#getObject
    // 接口实现的方法是 createBean(beanName, mbd, args)
	sharedInstance = getSingleton(beanName, () -> {
		return createBean(beanName, mbd, args);
		// 省略了 try / catch
	});
	bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

Veamos qué hace el método getSingleton ():

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
	Assert.notNull(beanName, "Bean name must not be null");
	// 注释 4.7 全局变量,加锁
	synchronized (this.singletonObjects) {
		//1、再次检查是否已经被加载了,单例模式就是可以复用已经创建的 bean
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null) {
			//2、初始化前操作,校验是否 beanName 是否有别的线程在初始化,并记录beanName的初始化状态
			beforeSingletonCreation(beanName);
			boolean newSingleton = false;
			boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
			if (recordSuppressedExceptions) {
				this.suppressedExceptions = new LinkedHashSet<>();
			}
			//3、调用createBean方法实例化bean
			singletonObject = singletonFactory.getObject();
			newSingleton = true;
			if (recordSuppressedExceptions) {
				this.suppressedExceptions = null;
			}
			//4、初始化后的操作,移除初始化状态
			afterSingletonCreation(beanName);
			if (newSingleton) {
				//5、加入缓存
				addSingleton(beanName, singletonObject);
			}
		}
		return singletonObject;
	}
}

El proceso de este paso es:

  • (1) Compruebe de nuevo si se ha cargado la caché
  • (2) Si no está cargado, registre el estado de carga de beanName
  • (3) Llame al método createBean () para instanciar el bean
  • (4) Una vez completada la instanciación del bean, elimine el estado de inicialización
  • (5) Registre el resultado de la instanciación en la caché y elimine los diversos estados auxiliares registrados durante el proceso de carga del frijol

Para los pasos (2) y (4), se usa para registrar el estado de carga del bean, que se usa para detectar dependencias circulares. El método clave se encuentra en el tercer paso, llamando al método getObject () de ObjectFactory. La interfaz de devolución de llamada real implementa el método createBean () para crear el objeto.

 

Tres, la fase de instanciación de Bean:

(1) Preparación antes de crear frijol:

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
	RootBeanDefinition mbdToUse = mbd;
	// 确保此时bean类已经被解析,并且克隆 bean 定义,以防动态解析的类不能存储在共享合并 bean 定义中。
	//1、锁定 class,根据设置的 class 属性或者根据 className 来解析 Class
	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}
	// Prepare method overrides.
	//2、验证及准备覆盖的方法
    mbdToUse.prepareMethodOverrides();
    //3、解析指定bean,让 beanPostProcessor 有机会返回代理而不是目标bean实例。
    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    if (bean != null) {
    	// 短路操作,如果代理成功创建 bean 后,直接返回
    	return bean;
    }
	
	//4、创建 bean
	Object beanInstance = doCreateBean(beanName, mbdToUse, args);
	return beanInstance;
}

Primero resumamos este proceso:

  • (1) Resolver clase de acuerdo con el atributo de clase establecido o de acuerdo con className
  • (2) El método de verificación y preparación para la cobertura Este método se utiliza para procesar las siguientes dos configuraciones: cuando analizamos la etiqueta predeterminada, reconoceremos los atributos del método de búsqueda y del método reemplazado, y luego la carga de estas dos configuraciones se almacenará de manera unificada en el atributo methodOverrides en beanDefinition.
  • (3) Aplique el postprocesador antes de la inicialización para analizar si el bean especificado tiene una operación de cortocircuito antes de la inicialización.
  • (4) Crea un frijol

1. Trate el atributo Anular:

public void prepareMethodOverrides() throws BeanDefinitionValidationException {
	// Check that lookup methods exists.
	if (hasMethodOverrides()) {
		Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
		synchronized (overrides) {
			for (MethodOverride mo : overrides) {
				// 处理 override 属性
				prepareMethodOverride(mo);
			}
		}
	}
}

Como puede ver, obtenga la lista de métodos sobrecargados de la clase, luego recorra y procese uno por uno. El procesamiento específico son los atributos de método de búsqueda y método reemplazado. La configuración analizada en este paso se almacenará en el atributo methodOverrides en beanDefinition en preparación para la instanciación más adelante. Si se detecta el atributo methodOverrides cuando se crea una instancia del bean, el bean actual se generará dinámicamente para generar un proxy y el interceptor correspondiente se utilizará para mejorar el bean.

2. Preprocesamiento antes de la instanciación:

// 让 beanPostProcessor 有机会返回代理而不是目标bean实例。
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
	// 短路操作,如果代理成功创建 bean 后,直接返回
	return bean;
}

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
	Object bean = null;
	if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
		// Make sure bean class is actually resolved at this point.
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			Class<?> targetType = determineTargetType(beanName, mbd);
			if (targetType != null) {
			    // 执行前置拦截器的操作
				bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
				if (bean != null) {
				    // 执行后置拦截器的操作
					bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
				}
			}
		}
		mbd.beforeInstantiationResolved = (bean != null);
	}
	return bean;
}

Antes del método doCreateBean (), hay una operación de cortocircuito.Si el postprocesador tiene éxito, se devolverá el bean proxy.

En el método resolveBeforeInstantiation (), se ejecutan dos métodos clave para asegurar que la información del bean ha sido analizada. De los comentarios, uno es la operación del pre-interceptor y el otro es la operación del post-interceptor.

Si el primer preinterceptor se instancia correctamente, el bean singleton se ha colocado en la caché. Ya no pasará por el proceso de creación de beans ordinarios y no hay posibilidad de realizar llamadas al postprocesador, así que aquí está el segundo. one El paso es que este bean también aplique el método postProcessAfterInitialization del postprocesador. Y si el frijol no tiene un preprocesamiento específico, significa que el frijol es un frijol ordinario, entonces siga los pasos a continuación para crear

(Dos) creación de frijoles: doCreateBean ()

En este paso, se crea realmente el objeto bean. El código fuente correspondiente está en el método doCreateBean (). Aquí, echemos un vistazo al proceso general de creación del bean, y luego hagamos los métodos importantes. Análisis:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) {
	// Instantiate the bean.
	BeanWrapper instanceWrapper = null;
    //1、如果bean是单例,就先清除缓存中的bean信息
	if (mbd.isSingleton()) {
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
		//2、根据指定bean使用对应的策略实例化bean,例如:工厂方法,构造函数自动注入,简单初始化
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	final Object bean = instanceWrapper.getWrappedInstance();
	Class<?> beanType = instanceWrapper.getWrappedClass();
	if (beanType != NullBean.class) {
		mbd.resolvedTargetType = beanType;
	}
	//3、允许后处理处理器修改合并后的bean定义
	synchronized (mbd.postProcessingLock) {
		if (!mbd.postProcessed) {
			applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
			mbd.postProcessed = true;
		}
	}
	//4、是否需要提前曝光,用来解决循环依赖时使用
	boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
			isSingletonCurrentlyInCreation(beanName));
	if (earlySingletonExposure) {
		// 第二个参数是回调接口,实现的功能是将切面动态织入 bean
		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	}
	Object exposedObject = bean;
    //5、对 bean 进行填充,将各个属性值注入
    // 如果存在对其它 bean 的依赖,将会递归初始化依赖的 bean
    populateBean(beanName, mbd, instanceWrapper);
    //6、调用初始化方法,例如 init-method
    exposedObject = initializeBean(beanName, exposedObject, mbd);
	
    //7、循环依赖检查
	if (earlySingletonExposure) {
		Object earlySingletonReference = getSingleton(beanName, false);
		// earlySingletonReference 只有在检测到有循环依赖的情况下才 不为空
		if (earlySingletonReference != null) {
			if (exposedObject == bean) {
				// 如果 exposedObject 没有在初始化方法中被改变,也就是没有被增强
				exposedObject = earlySingletonReference;
			}
			else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
				String[] dependentBeans = getDependentBeans(beanName);
				Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
				for (String dependentBean : dependentBeans) {
					// 检查依赖
					if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
						actualDependentBeans.add(dependentBean);
					}
				}
				// bean 创建后,它所依赖的 bean 一定是已经创建了
				// 在上面已经找到它有依赖的 bean,如果 actualDependentBeans 不为空
				// 表示还有依赖的 bean 没有初始化完成,也就是存在循环依赖
				if (!actualDependentBeans.isEmpty()) {
					throw new BeanCurrentlyInCreationException(beanName);
			}
		}
	}
	// Register bean as disposable.
	// 8、根据 scope 注册 bean
	registerDisposableBeanIfNecessary(beanName, bean, mbd);
	return exposedObject;
}

El flujo principal de este método doCreateBean () se puede resumir como:

  • (1) Si el bean que se va a cargar es un singleton, primero borre la información del bean en la caché
  • (2) Instanciar bean, convertir BeanDifinition en BeanWrapper
  • (3) El postprocesador modifica la definición de bean fusionado: el procesamiento del bean fusionado, la anotación Autowired implementa formalmente un pre-análisis como el tipo a través de este método
  • (4) Manejo de dependencias, exponiendo las referencias de frijol de antemano, utilizado principalmente para resolver el problema de las dependencias circulares
  • (5) Relleno de atributos: complete todos los atributos en la instancia del bean, si hay una dependencia de otros beans, el bean dependiente se inicializará de forma recursiva
  • (6) Bean de inicialización: como afeterPropertiesSet () y método de configuración de propiedades del método init
  • (7) Comprobación de dependencia circular
  • (8) Registrar DisposableBean: Este paso se utiliza para procesar el atributo del método de destrucción. Regístrese en este paso para que se pueda llamar cuando el objeto sea destruido.
  • (9) Completa la creación y regresa.

1, createBeanInstance (): instancia el objeto bean

En el paso anterior (2), lo que se hace es instanciar el bean y luego volver al BeanWrapper.

El proceso de este paso de createBeanInstance () instancia principalmente el objeto bean de dos maneras, una es el método de fábrica y la otra es el constructor. La configuración en la RootBeanDefinition pasada se selecciona para generar una instancia de bean, y la función es aproximadamente presentado:

  • Si hay un método de fábrica, use el método de fábrica para la inicialización
  • Si usa líneas de construcción parametrizadas para instanciar el bean: una clase tiene múltiples constructores, y cada constructor tiene diferentes parámetros, por lo que necesita bloquear el constructor de acuerdo con los parámetros para instanciar el bean
  • Si no hay un método de fábrica ni un constructor con parámetros, se usará el constructor predeterminado para instanciar el bean
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
	// Make sure bean class is actually resolved at this point.
	Class<?> beanClass = resolveBeanClass(mbd, beanName);
	Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
	// Shortcut when re-creating the same bean...
	boolean resolved = false;
	boolean autowireNecessary = false;
	if (args == null) {
		synchronized (mbd.constructorArgumentLock) {
			// 如果一个类有多个构造函数,每个构造函数都有不同的参数,调用前需要进行判断对应的构造函数或者工厂方法
			if (mbd.resolvedConstructorOrFactoryMethod != null) {
				resolved = true;
				autowireNecessary = mbd.constructorArgumentsResolved;
			}
		}
	}
	// 如果已经解析过,不需要再次解析
	if (resolved) {
		if (autowireNecessary) {
			// 实际解析的是 org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor
			// 构造函数自动注入
			return autowireConstructor(beanName, mbd, null, null);
		}
		else {
			// 使用默认的构造函数
			return instantiateBean(beanName, mbd);
		}
	}
    // Candidate constructors for autowiring? 需要根据参数解析构造函数
	Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
	if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
			mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
		return autowireConstructor(beanName, mbd, ctors, args);
	}
	// Preferred constructors for default construction?
	ctors = mbd.getPreferredConstructors();
	if (ctors != null) {
		// 构造函数注入
		return autowireConstructor(beanName, mbd, ctors, null);
	}
	// No special handling: simply use no-arg constructor. 没有特殊的处理,使用默认构造函数构造
	return instantiateBean(beanName, mbd);
}

Aquí, presentamos brevemente qué es BeanWrapper:

Los Beans en Spring no existen en su apariencia original. Dado que el contenedor Spring IOC tiene que administrar múltiples tipos de objetos, para unificar el acceso a diferentes tipos de objetos, Spring pone una capa en todas las instancias de Bean creadas. esta chaqueta es BeanWrapper, BeanWrapper en realidad es un paquete simple que refleja la API relevante, haciendo uso del reflector superior completar la lógica comercial relevante simplificar enormemente, queremos obtener las propiedades de un objeto, la llamada al método de un objeto, no ahora Necesita escriba API de reflexión complicadas y maneje un montón de excepciones problemáticas.Puede completar operaciones relacionadas directamente a través de BeanWrapper, lo cual no es demasiado bueno.

2. Dependencia circular:

Esto corresponde al proceso del paso anterior (4), exponiendo las referencias de frijol de antemano, principalmente para resolver el problema de las dependencias circulares

// 是否需要提前曝光,用来解决循环依赖时使用
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
		isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
	// 第二个参数是回调接口,实现的功能是将切面动态织入 bean
	addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

El método clave es addSingletonFactory, que se usa para agregar ObjectFactory que crea la instancia a la fábrica singleton antes de que el bean comience a inicializarse. ObjectFactory es la fábrica que se usa al crear objetos. Cuando se crea una instancia del objeto, juzgará si el objeto del que depende se ha creado. La base del juicio es comprobar si la ObjectFactory del objeto dependiente está en la caché singleton. Si no se crea, el objeto dependiente se creará primero, y luego se colocará la ObjectFactory en la caché Singleton.

Si hay una dependencia circular en este momento, debe exponerse con anticipación para que la parte que confía pueda encontrarla e instanciarla normalmente.

Puede leer este artículo sobre dependencias circulares: https://blog.csdn.net/a745233700/article/details/110914620

3. populateBean (): inyección de atributo

Esto corresponde al paso anterior (5), llenando los atributos de acuerdo con los diferentes tipos de inyección, y luego llamando al postprocesador para su procesamiento y finalmente aplicando los atributos al bean. El proceso principal es el siguiente:

(1) Llame al método postProcessAfterInstantiation del procesador InstantiationAwareBeanPostProcessor para determinar si el programa de control continúa completando los atributos

(2) De acuerdo con el tipo de inyección (byType / byName), extraiga las dependencias y almacénelas en PropertyValues ​​de manera uniforme

(3) Determine si se necesitan BeanPostProcessor y verificación de dependencia:

  • Si hay un postprocesador, se utilizará el método postProcessProperties del procesador InstantiationAwareBeanPostProcessor para procesar las propiedades nuevamente antes de que se obtengan y se completen.
  • Utilice el método checkDependencies para comprobar las dependencias

(4) Complete todas las propiedades analizadas en PropertyValues ​​en BeanWrapper

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
	// 给 awareBeanPostProcessor 后处理器最后一次机会,在属性设置之前修改bean的属性
	boolean continueWithPropertyPopulation = true;
	if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
		...
        if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
			continueWithPropertyPopulation = false;
			break;
		}
        ...
	}
	PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
	int resolvedAutowireMode = mbd.getResolvedAutowireMode();
	if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
		MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
		// Add property values based on autowire by name if applicable.
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
			// 根据名字自动注入
			autowireByName(beanName, mbd, bw, newPvs);
		}
		// Add property values based on autowire by type if applicable.
		if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			// 根据类型自动注入
			autowireByType(beanName, mbd, bw, newPvs);
		}
		pvs = newPvs;
	}
	// 后处理器已经初始化
	boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
	// 需要依赖检查
	boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
	PropertyDescriptor[] filteredPds = null;
    // 从 beanPostProcessors 对象中提取 BeanPostProcessor 结果集,遍历后处理器
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
    	...
    }
	// 在前面也出现过,用来进行依赖检查
    filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
    checkDependencies(beanName, mbd, filteredPds, pvs);
	// 将属性应用到 bean 中,使用深拷贝,将子类的属性一并拷贝
	applyPropertyValues(beanName, mbd, bw, pvs);
}

4. initializeBean (): inicializa el bean

Esto corresponde al paso anterior (6), que se usa principalmente para llamar al método de inicialización que configuramos, pero dentro del método, también se realizan otras operaciones. Primero, veamos el código fuente:

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    //1、处理Aware接口
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
			invokeAwareMethods(beanName, bean);
			return null;
		}, getAccessControlContext());
	}
	else {
		// 如果没有 securityManage,方法里面校验了 bean 的类型,需要引用 Aware 接口
		// 对特殊的 bean 处理:Aware/ BeanClassLoader / BeanFactoryAware
		invokeAwareMethods(beanName, bean);
	}

    //2、执行BeanPostProcessor前置处理:
	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}
	//3、调用用户自定义的 init-method 方法
	invokeInitMethods(beanName, wrappedBean, mbd);

    //4、执行BeanPostProcessor后置处理
	if (mbd == null || !mbd.isSynthetic()) {
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}

	return wrappedBean;
}

En este paso del proceso, las principales operaciones de procesamiento son:

(1) Interfaz de Processing Aware:

Spring detectará si el objeto implementa la interfaz xxxAware. A través de la interfaz de tipo Aware, podemos obtener algunos recursos correspondientes del contenedor Spring e inyectarlos:

  • ① Si este Bean implementa la interfaz BeanNameAware, llamará al método setBeanName (String beanId) que implementa y pasará el nombre del Bean;
  • ② Si este Bean implementa la interfaz BeanClassLoaderAware, llame al método setBeanClassLoader () y pase la instancia del objeto ClassLoader.
  • ② Si este Bean implementa la interfaz BeanFactoryAware, llamará al método setBeanFactory () que implementa, pasando la propia fábrica Spring.
  • ③Si este Bean implementa la interfaz ApplicationContextAware, llamará al método setApplicationContext (ApplicationContext) y pasará el contexto Spring;

(2) Ejecute el preprocesamiento de BeanPostProcessor:

Si desea realizar algún preprocesamiento personalizado antes de que se inicialice el Bean, puede hacer que el Bean implemente la interfaz BeanPostProcessor, que llamará al método postProcessBeforeInitialization (Object obj, String s).

(3) Llame al método de inicio personalizado:

Este paso es encontrar el constructor definido por el usuario y luego llamarlo.

① Si el Bean implementa la interfaz InitializingBean, ejecute el método afeterPropertiesSet ()

② Si el bean está configurado con el atributo init-method en el archivo de configuración de Spring, automáticamente llamará a su método de inicialización configurado.

(4) Ejecute el posprocesamiento de BeanPostProcessor:

Si el Bean implementa la interfaz BeanPostProcessor, se llamará al método postProcessAfterInitialization (Object obj, String s); dado que este método se llama al final de la inicialización del Bean, se puede aplicar a la memoria o la tecnología de almacenamiento en caché;

En la fase de inicio del contenedor, hablamos de BeanFactoryPostProcessor, aquí hablamos de BeanPostProcessor, entonces ¿cuál es la diferencia entre BeanFactoryPostProcessor y BeanPostProcessor?

  • BeanFactoryPostProcessor existe en la etapa de inicio del contenedor, mientras que BeanPostProcessor existe en la etapa de instanciación del objeto. BeanFactoryPostProcessor se enfoca en la modificación de la configuración antes de que se cree el objeto, mientras que la etapa BeanPostProcessor se enfoca en la mejora de funciones, reemplazo y otras operaciones después de que el objeto ha sido creado , para que sea fácil de distinguir.
  • BeanPostProcessor y BeanFactoryPostProcessor son dos poderosos puntos de extensión de Spring en el proceso de producción de frijoles. El famoso AOP (Programación Orientada a Aspectos) de Spring en realidad se basa en BeanPostProcessor para mejorar la función del objeto Bean.

5. Registre el frijol desechable:

Este paso consiste en registrar el bean desechable de acuerdo con diferentes ámbitos. Al mismo tiempo, se registrará la lógica de destrucción definida por el usuario.Hay dos formas como la lógica de inicialización personalizada: (1) destroy () de la interfaz DisposableBean, (2) el método de configuración de parámetros del método destroy.

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
	AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
	if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
        // 单例模式
		if (mbd.isSingleton()) {
			// 注册 DisposableBean
			registerDisposableBean(beanName,new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
		}
		else {
			// A bean with a custom scope...
			Scope scope = this.scopes.get(mbd.getScope());
			scope.registerDestructionCallback(beanName,new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
		}
	}
}

6. Uso y destrucción:

Después de los pasos anteriores, Spring finalmente ha completado la creación del Bean. Cuando el Spring Bean termine de servirnos, pronto morirá (generalmente cuando el contenedor está cerrado). En este momento, Spring nos llamará en un modo de devolución de llamada. ¡Lógica de destrucción personalizada, y luego Bean terminó su gloriosa vida de esta manera!

7. Resumen:

Finalmente, echemos un vistazo al orden de ejecución de la fase de instanciación de Bean a través de una imagen:

 

Articulo de referencia:

https://juejin.cn/post/6844903871353978894#heading-5

https://juejin.cn/post/6929672218322731022#heading-0

Supongo que te gusta

Origin blog.csdn.net/a745233700/article/details/113840727
Recomendado
Clasificación