一、注入依赖后初始化

下面是doCreateBean的部分代码:

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

在上一节中,Spring通过populateBean已经完成了依赖注入,也就是将<bean>节点中的property属性和@Autowired注解的依赖注入到了创建好的bean中,下一步就是完成初始化。初始化包括:各种Awre接口功能、init方法调用、BeanPostProcessor的调用,具体代码如下:

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			//调用Aware接口方法(如果实现了Aware接口的话)
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			//调用BeanPostProcessor的postProcessBeforeInitialization方法
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			//如果bean实现了InitializingBean接口,那么会直接调用afterPropertiesSet方法
			//如果<bean>节点中配置了init-method,会通过反射调用init-method指定的方法
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(...);
		}
		if (mbd == null || !mbd.isSynthetic()) {
			//调用BeanPostProcessor的postProcessAfterInitialization方法
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

上面代码的步骤为:

  1. 调用Aware接口方法,将Aware对应的值设置到bean中(具体设置代码,是用户继承Aware接口是自己实现的)。BeanFactory支持的Aware接口包括:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
  2. 调用BeanPostProcessor的postProcessBeforeInitialization方法
  3. 调用InitializingBean接口的afterPropertiesSet方法(直接调用),或者调用<bean>节点中配置的init-method(通过反射调用)
  4. 调用BeanPostProcessor的postProcessAfterInitialization方法

1、Aware接口功能

对于Aware的功能实现较为简单,首先判断bean是否继承自Aware接口,如果是的话,再判断Bean具体的Aware类型,然后调用相应的方法:

private void invokeAwareMethods(final String beanName, final Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}
			if (bean instanceof BeanClassLoaderAware) {
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) {
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				}
			}
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}

2、BeanPostProcessor后处理器

BeanPostProcessor是Spring提供给用户一个修改bean状态的机会(此时的bean属性已经设置完成),调用实际分别在初始化前后:

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
			Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}
	
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

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

3、init-method或InitializingBean接口功能

Spring提供了一个初始化bean的功能,在bean完成了属性填充后,调用用户指定的方法。该方法指定方式用两种:

  1. xml文件中为<bean>节点配置init-method
  2. 让bean继承InitializingBean接口,覆写其afterPropertiesSet方法

下面是Spring调用初始化方法的代码:

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {
		//如果bean继承自InitializingBean,直接调用其afterPropertiesSet方法
		boolean isInitializingBean = (bean instanceof InitializingBean);
		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
			if (System.getSecurityManager() != null) {
				try {
					AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
						((InitializingBean) bean).afterPropertiesSet();
						return null;
					}, getAccessControlContext());
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				((InitializingBean) bean).afterPropertiesSet();
			}
		}
		//-----------------------------------------------------------------
		
		//调用配置的init-method
		if (mbd != null && bean.getClass() != NullBean.class) {
			String initMethodName = mbd.getInitMethodName();
			if (StringUtils.hasLength(initMethodName) &&
					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) {
				//通过反射调用init-method
				invokeCustomInitMethod(beanName, bean, mbd);
			}
		}
	}

invokeCustomInitMethod通过反射获取class中同名、无参的方法Method对象,通过Method的invoke方法完成调用:

protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd)
			throws Throwable {
		//获取init-method属性
		String initMethodName = mbd.getInitMethodName();
		Assert.state(initMethodName != null, "No init method set");
		//通过反射,获取class中对应名称的Method对象
		final Method initMethod = (mbd.isNonPublicAccessAllowed() ?
				BeanUtils.findMethod(bean.getClass(), initMethodName) :
				ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
		//未找到对应的Method对象
		if (initMethod == null) {
			//如果BeanDefinition中强制要求执行init-method(默认为true),则抛出异常
			if (mbd.isEnforceInitMethod()) {
				throw new BeanDefinitionValidationException("Couldn't find an init method named '" +
						initMethodName + "' on bean with name '" + beanName + "'");
			}
			//否则只是打印错误信息
			else {
				//日志打印,略
				return;
			}
		}

		//通过Method的invoke方法,调用init-method
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				ReflectionUtils.makeAccessible(initMethod);
				return null;
			});
			try {
				AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () ->
					initMethod.invoke(bean), getAccessControlContext());
			}
			catch ...
		}
		else {
			try {
				ReflectionUtils.makeAccessible(initMethod);
				initMethod.invoke(bean);
			}
			catch ...
		}
	}