Spring IOC(三)createBean方法源码分析——创建Bean之前的准备工作


以BeanFactory的createBean方法为入口,整理Bean的创建流程。
createBean方法的核心功能:创建一个Bean实例、填充Bean实例、应用后处理器等。

/**
	 * Central method of this class: creates a bean instance,
	 * populates the bean instance, applies post-processors, etc.
	 * @see #doCreateBean
	 */
	@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;

		// Make sure bean class is actually resolved at this point, and
		// clone the bean definition in case of a dynamically resolved Class
		// which cannot be stored in the shared merged bean definition.
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

		// Prepare method overrides.
		try {
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isDebugEnabled()) {
			logger.debug("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}

这个方法的大概功能包括了:

  1. prepareMethodOverrides,准备BeanDefinition中MethodOverrides属性的准备操作
  2. resolveBeforeInstantiation,在实例化之前,决定是否直接返回BeanPostProcessors的代理对象
  3. doCreateBean,进入真正创建的操作

第1步:prepareMethodOverrides

public void prepareMethodOverrides() throws BeanDefinitionValidationException {
		// Check that lookup methods exists.
		MethodOverrides methodOverrides = getMethodOverrides();
		if (!methodOverrides.isEmpty()) {
			for (MethodOverride mo : methodOverrides.getOverrides()) {
				prepareMethodOverride(mo);
			}
		}
	}
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
		int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
		if (count == 0) {
			throw new BeanDefinitionValidationException(
					"Invalid method override: no method with name '" + mo.getMethodName() +
					"' on class [" + getBeanClassName() + "]");
		}
		else if (count == 1) {
			// Mark override as not overloaded, to avoid the overhead of arg type checking.
			mo.setOverloaded(false);
		}
	}

其中的getMethodOverrides()取的是BeanDefinition中的MethodOverrides属性。

  • 而MethodOverrides是何时被赋值的呢?
    在xml解析阶段,将lookup-method和replace-method两个标签属性,存在了MethodOverrides中。详细解释见附1。
  • 取出所有此类方法,prepareMethodOverride的作用是什么?
    我们可以看到getMethodCountForName中,将此Bean中所有的methodName符合的方法都取出并记录个数,如果只有1个,给这个方法记录为"没有被重载",可以省去之后代理这个方法时的类型检查匹配工作。

第2步:resolveBeforeInstantiation

/**
	 * Apply before-instantiation post-processors, resolving whether there is a
	 * before-instantiation shortcut for the specified bean.
	 * @param beanName the name of the bean
	 * @param mbd the bean definition for the bean
	 * @return the shortcut-determined bean instance, or {@code null} if none
	 */
	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;
	}

在这个方法中,功能包括了:

  1. hasInstantiationAwareBeanPostProcessors,确定此Bean中是否存在InstantiationAwareBeanPostProcessor,存在的话再向下进行
  2. determineTargetType,确定BeanDefinition的targetType,主要是针对含有FactoryMethod的Bean进行特殊处理
  3. applyBeanPostProcessorsBeforeInstantiation,回调BeanPostProcessor.postProcessBeforeInstantiation进行Bean的创建过程代理
  4. applyBeanPostProcessorsAfterInitialization,回调InstantiationAwareBeanPostProcessor.postProcessAfterInitializationbean实例的代理封装

第2-3步:applyBeanPostProcessorsBeforeInstantiation

/**
	 * Apply InstantiationAwareBeanPostProcessors to the specified bean definition
	 * (by class and name), invoking their {@code postProcessBeforeInstantiation} methods.
	 * <p>Any returned object will be used as the bean instead of actually instantiating
	 * the target bean. A {@code null} return value from the post-processor will
	 * result in the target bean being instantiated.
	 * @param beanClass the class of the bean to be instantiated
	 * @param beanName the name of the bean
	 * @return the bean object to use instead of a default instance of the target bean, or {@code null}
	 * @throws BeansException if any post-processing failed
	 * @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
	 */
	protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName)
			throws BeansException {

		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
				if (result != null) {
					return result;
				}
			}
		}
		return null;
	}

这个方法中,获取全部的InstantiationAwareBeanPostProcessor,然后遍历执行其postProcessBeforeInstantiation方法。
有关InstantiationAwareBeanPostProcessor详细解释见附3。

第2-4步:applyBeanPostProcessorsAfterInitialization

@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
			result = beanProcessor.postProcessAfterInitialization(result, beanName);
			if (result == null) {
				return result;
			}
		}
		return result;
	}

这个方法中,获取全部的BeanPostProcessor,然后遍历执行其postProcessAfterInitialization方法。
有关BeanPostProcessor详细解释见附2。

第3步:doCreateBean(下篇详细分析)

附1.lookup-method、replace-method实现MethodOverride

这两个标签的意义是对Bean中的某个方法实现动态注入,如lookup-method的作用在于配置将某个method的返回Bean进行替换:

<context:component-scan base-package="example"/>
 <bean id="animalManager" class="example.methodoverride.AnimalManager">
        <lookup-method name="getAnimal" bean="cat"/>
 </bean>
@Component
public class Animal {


}
@Component
public class Cat extends Animal {

}
@Component
public class AnimalManager {
    public Animal getAnimal() {
        return new Animal();
    }
}
public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("spring/applicationContext.xml");
        AnimalManager animalManager = ac.getBean(AnimalManager.class);
        System.out.println(animalManager.getAnimal().getClass().getName())}

最后的输出结果是:

example.methodoverride.Cat

当然,如果xml中没有配置属性,输出结果是:

example.methodoverride.Animal

与lookup-method类似,replace-method除了可以替换方法的返回值之外,还可以将方法的逻辑进行修改。

附2.BeanPostProcessor

public interface BeanPostProcessor {

	Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

	Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

BeanPostProcessor接口是允许自定义修改新bean实例的工厂钩子,例如检查标记接口或用代理包装它们。
ApplicationContexts可以在其bean定义中自动检测BeanPostProcessor bean,并将它们应用于随后创建的任何bean。而普通bean工厂允许编程注册后处理器,应用于通过该工厂创建的所有bean,这也是我们所说的ApplicationContext的丰富功能之一。

  • postProcessBeforeInitialization:
    在Bean实例的初始化方法回调之前,调用BeanPostProcessor的postProcessBeforeInitialization的方法进行bean实例属性的填充。
  • postProcessAfterInitialization:
    在Bean实例的初始化方法回调之后调用BeanPostProcessor的postProcessAfterInitialization的方法,可以进行bean实例的代理封装。对于FactoryBean的类型,这个回调将应用到FactoryBean实例和FactoryBean创建的对象两者。与所有其他BeanPostProcessor回调相比,这个回调也将在一个 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation方法触发短路之后 被调用。

注意Initialization:这两个方法的执行时机是Bean的 初始化方法前后 (afterPropertiesSet或自定义的init方法)。

附3.InstantiationAwareBeanPostProcessor

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor{
   
    Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;
   
    boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;
  
    PropertyValues postProcessPropertyValues(
      PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
      throws BeansException;
}

InstantiationAwareBeanPostProcessor是BeanPostProcessor的子接口,除了原有的三个接口外,添加了实例化前的回调,以及实例化后但在属性赋值(显示声明属性或者自动装配)之前的回调。
通常用于抑制特定目标bean的默认实例化,例如创建具有特殊目标源(pooling targets,lazily initializing targets, etc)的代理,或者实现额外的注入策略,如字段注入。
这个接口是一个特殊用途的接口,主要用于框架内的内部使用。建议尽可能实现普通的 BeanPostProcessor接口,或者从InstantiationAwareBeanPostProcessorAdapter派生,以便屏蔽对该接口的扩展。

  • postProcessBeforeInstantiation
    在Bean的实例化之前被调用(对factory-method没有用),此时返回的Object会代替原本要实例化生成的对象,也就是动态代理。如果返回的不为null,代表此Bean的创建过程被短路。唯一应用的进一步处理是自已配置的BeanPostProcessor#postProcessAfterInitialization回调。
  • postProcessAfterInstantiation
    在Bean的实例化之后(factory-method或者构造器),属性赋值之前,返回的boolean决定了是否要对属性进行赋值。一般都是返回true。AutowiredAnnotationBeanPostProcessor是一个经典例子。
  • postProcessPropertyValues
    通常是通过基于原始的PropertyValues创建一个新的MutablePropertyValues实例,添加或删除特定的值。

注意Instantiation:这三个方法的执行时机是Bean的 实例化前后

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值