欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

《Spring设计思想》11-如果上天再给你一次机会

程序员文章站 2022-05-23 15:46:47
...

第9节书中写道:紫霞仙子的剑离秦祥林的喉咙只有0.01厘米,但是至尊宝撒了一个谎,这个谎导致紫霞仙子彻底的爱上了他,但是他万万没想到,这是一个悲剧的开始。紫霞仙子还是被捉去被强迫成亲,而他自己拿了月光宝盒逃跑。。。

所以第10节紫霞仙子还是默认进行了实例化,这个时候她穿好了嫁衣,马上就要拜堂了。他的意中人到底能不能来接他

这一节我们书接上文,继续看看bean被实例化之后有什么操作。

还是AbstractAutowireCapableBeanFactory.createBean(String beanName,RootBeanDefinition mbd,Object[] args)方法

调用AbstractAutowireCapableBeanFactory.doCreateBean(String beanName,RootBeanDefintion mbd,Object[] args)方法

	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.实例化bean
		BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
	
		final Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();

        
		// Initialize the bean instance. 初始化bean
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			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);
			}
		}

		return exposedObject;
	}

方法中可以看到bean在实例化之后要执行初始化操作

1:populateBean(beanName,mbd,instanceWrapper);注入bean的配置属性

2:exposedObject = initializeBean(beanName,exposedObject,mbd);初始化bean,调用aware的回调接口,和beanPostProcessor

简单的看下populateBean(beanName,mbd,instanceWrapper);

	/**
	 * Populate the bean instance in the given BeanWrapper with the property values
	 * from the bean definition.
	 * @param beanName the name of the bean
	 * @param mbd the bean definition for the bean
	 * @param bw the BeanWrapper with bean instance
	 */
	@SuppressWarnings("deprecation")  // for postProcessPropertyValues
	protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
		

		// 着重强调,我要给至尊宝一次机会,让他阻止当前的婚礼Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
		// state of the bean before properties are set. This can be used, for example,
		// to support styles of field injection.
		boolean continueWithPropertyPopulation = true;

		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						continueWithPropertyPopulation = false;
						break;
					}
				}
			}
		}

		if (!continueWithPropertyPopulation) {
			return;
		}

		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		PropertyDescriptor[] filteredPds = null;
		if (hasInstAwareBpps) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				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;
				}
			}
		}

		if (pvs != null) {
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}

看到属性:continueWithPropertyPopulation的时候,我心里流下了感动的泪水,这个地方是紫霞仙子给至尊宝留下的一个机会,让他可以终止当前的婚礼,还是前面讲到的接口InstantiationAwareBeanPostProcessor:

《Spring设计思想》11-如果上天再给你一次机会

第9节描述的是postProcessorBeforeInstantiation方法,这个地方调用的是posrProcessorAfterInstantiation(Object,String)

看简单的实现

public class BeanInstantiaitionAwareImpl implements InstantiationAwareBeanPostProcessor {

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
//        Assert.isNull(beanClass,"beanClass不能为空");
        if(ObjectUtils.nullSafeEquals(beanClass, SuperUser.class)){
            SuperUser superUser = new SuperUser();
            superUser.setName("一个船新的版本");
            superUser.setAge(22);
            return superUser;
        }
        //默认什么都不做,返回null,继续下一步实例化
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if(bean.getClass().equals(User.class)){
            User user = (User) bean;
            user.setName("至尊宝");
            user.setAge(589);
            return false;
        }
        //默认返回true,什么也不做,继续下一步 初始化
        return true;
    }
}

断点调试:

《Spring设计思想》11-如果上天再给你一次机会

调用堆栈

《Spring设计思想》11-如果上天再给你一次机会

不再继续populateBean方法,

《Spring设计思想》11-如果上天再给你一次机会

看输出结果:

至尊宝来了:

《Spring设计思想》11-如果上天再给你一次机会

到这里我们看到,InstantiationAwareBeanPostProcessor的两个方法

postProcessorBeforeInstantiation在实例化之前调用

postProcessorAfterInstantiation在实例化之后,初始化之前调用。