Spring系列之实例化、初始化处理器

2020-09-03 11:32:12 浏览数 (1)

概念

谈论到实例化处理器和初始化处理器,我们要明确一个实例化和初始化概念,大牛们可以忽略此处说明。

  • 实例化:指创建类实例(对象)的过程。比如使用构造方法new对象,为对象在内存中分配空间。(要创建对象,但是并未生成对象)
  • 初始化:指为类中各个类成员(被static修饰的成员变量)赋初始值的过程,是类生命周期中的一个阶段。简单理解为对象中的属性赋值的过程。(对象已经生成,为其属性赋值)

源码

从源码解读实例化处理器和初始化处理器。

  1. InstantiationAwareBeanPostProcessor 该接口继承自BeanPostProcessor接口,并自定义如图方法。
  • postProcessBeforeInstantiation 实例化前置处理 (对象未生成)
  • postProcessAfterInstantiation 实例化后置处理 (对象已经生成)
  • postProcessPropertyValues 修改属性值。(对象已经生成)
  1. BeanPostProcessor
  • postProcessBeforeInitialization初始化前置处理 (对象已经生成)
  • postProcessAfterInitialization初始化后置处理 (对象已经生成)

触发处理器时机

从Bean的生命周期流程中可知,实例化和初始化处理器作用时机主要在初始化Bean前后。 主要在类AbstractAutowireCapableBeanFactory

代码语言:javascript复制
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating instance of bean '"   beanName   "'");
		}
		RootBeanDefinition mbdToUse = mbd;
		//根据设置的class属性或者根据className来解析class:调用AbstractBeanFactory类
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}
		// Prepare method overrides.
		try {
			//验证以及准备覆盖的方法即Override方法
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}
		try {
			//返回代理来代替真正的实例:--------------应用实例化前的前置处理器
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			//短路操作,返回bean
			if (bean != null) {
				//返回bean的代理对象
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		//---------------创建单例bean对象:核心方法doCreateBean(常规bean的创建过程)
		try {
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isTraceEnabled()) {
				logger.trace("Finished creating instance of bean '"   beanName   "'");
			}
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			// A previously detected exception with proper bean creation context already,
			// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}
  1. 触发postProcessBeforeInstantiation时机 postProcessBeforeInstantiation调用时机: BeanDefinition创建Bean的开端是在createBean()方法也就是流水线的开始处。 注意是否返回bean的代理对象,如果返回Bean的代理对象,则直接return代理对象;即resolveBeforeInstantiation()方法,源代码如下
代码语言:javascript复制
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			//是否实现前置处理器接口
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
					//调用InstantiationAwareBeanPostProcessor:实例化前置处理器
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						//调用初始化后置处理器,doCreateBean流程结束
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}

解释说明:

  • 首先,判断是否存在InstantiationAwareBeanPostProcessor接口的处理器
  • 如存在,则调用的是InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation()实例化前置处理方法,也就是在Bean对象没有生成之前执行(实例化过程中)。(注意:这里所说的是Bean未生成指的是Bean没有走spring定义创建Bean的流程,也就是doCreateBean()方法。)
  • 如果postProcessBeforeInstantiation()返回的对象不为空, 意味着Bean对象已经存在,表明对象已经初始化完成。然后调用postProcessAfterInitialization()初始化后置处理器,完成对Bean对象的操作. 如果postProcessBeforeInstantiation()返回值为空,则进入上层调用者createBean()方法,继续调用doCreateBean()方法,完成对象实例化(创建对象),以及对象初始化.
  1. postProcessAfterInstantiation调用时机 上面createBean()方法中标识若resolveBeforeInstantiation()方法没有返回bean,则调用doCreateBean()方法,进入创建bean流程中; 下面我们开始分析doCreateBean()的部分代码
代码语言:javascript复制
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {
			...//省略部分源码
		// Initialize the bean instance.
		//------------------------完成实例化bean创建,下面开始进行------bean初始化操作-------------
		Object exposedObject = bean;
		try {
			//----****属性填充操作:其中可能会存在依赖其他bean属性,则会递归初始化依赖bean****
			populateBean(beanName, mbd, instanceWrapper);
			//--- ****初始化指定的bean实例*****,回调init()方法和执行处理器
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}
		...//省略后面代码
		}

跟踪populateBean()方法的源码实现,便可以发现postProcessAfterInstantiation() 与postProcessPropertyValues()依次被执行。该方法仍然处于实例化过程

代码语言:javascript复制
...省略部分源码
//是否实现InstantiationAwareBeanPostProcessor接口,以及bean是否依赖检查
		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		PropertyDescriptor[] filteredPds = null;
		//处理实现了InstantiationAwareBeanPostProcessor
		if (hasInstAwareBpps) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				//一次调用实现的InstantiationAwareBeanPostProcessor接口的postProcessPropertyValues方法
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						if (filteredPds == null) {
							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
						}
						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvsToUse == null) {
							return;
						}
					}
					pvs = pvsToUse;
				}
			}
		}
  1. postProcessBeforeInitialization、 postProcessAfterInitialization 初始化前后处理器,从initializeBean()方法中依次被调用执行
代码语言:javascript复制
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		//如果bean是BeanNameAware,BeanClassLoaderAware或者BeanFactoryAware其中某一个的实现类就需要进行处理
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}
		Object wrappedBean = bean;
		//bean生命周期之一:如果实现了BeanPostProcessor接口,则会在此调用实现类中的beanPostProcessorsBeforeInitialization()方法
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			//bean生命周期之一:如果实现InitializingBean接口,则会在此调用实现类中的afterPropertiesSet()方法
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		//bean生命周期之一:如果实现了BeanPostProcessor接口,则会在此调用实现类中的beanPostProcessorAfterInitialization()方法
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}

总结

  1. BeanPostProcessor定义的方法是在对象初始化过程中做处理,分别在resolveBeforeInstantiation()触发后置处理器,或者在initializeBean依次调用前后处理器。
  2. InstantiationAwareBeanPostProcessor定义的方法是在对象实例化过程中做处理,即分别在resolveBeforeInstantiation()、populateBean()触发前置处理器,后置处理器。 从上面分析可知: 实例化—>初始化过程中会形成两条路径。
  • postProcessBeforeInstantiation()–自定义对象–>postProcessAfterInitialization();
  • postProcessBeforeInstantiation() -->postProcessAfterInstantiation–>postProcessBeforeInitialization()–>postProcessAfterInitialization() postProcessBeforeInstantiation一定执行, postProcessAfterInitialization一定执行.

参考资料:https://juejin.im/post/5da995d25188256a49204d7b

0 人点赞