【Spring源码学习】Spring Bean实例化过程-初始化


上一章讲完了populateBean的过程,这一章,我们来跟一下bean初始化的流程,主要分为这么几个步骤:

  • 调用Aware方法
  • InitializingBean接口,afterPropertiesSet,init-method属性调用

一、调用Aware方法

1.InitializeBean()

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
			invokeAwareMethods(beanName, bean);
			return null;
		}, getAccessControlContext());
	}
	else {
		//1.调用Aware方法
		invokeAwareMethods(beanName, bean);
	}

	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
		//前置处理
		//对类中某些特殊方法的调用,比如@PostConstruct,Aware接口,非常重要 重要程度 :5
		//ApplicationContextAwareProcessor 对Aware接口的调用如:
		//EnvironmentAware EmbeddedValueResolverAware  ResourceLoaderAware ApplicationEventPublisherAware MessageSourceAware  ApplicationContextAware
		//ImportAwareBeanPostProcessor 对ImportAware的支持
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}

	try {
		//2.InitializingBean接口,afterPropertiesSet,init-method属性调用,非常重要,重要程度:5
		invokeInitMethods(beanName, wrappedBean, mbd);
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				(mbd != null ? mbd.getResourceDescription() : null),
				beanName, "Invocation of init method failed", ex);
	}
	if (mbd == null || !mbd.isSynthetic()) {
		//3.后置处理,这个地方可能生出代理实例,是aop的入口
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}

	return wrappedBean;
}

2.invokeAwareMethods()

这个方法主要是设置beanName,beanClassLoader,beanFactory,但前提是这个bean实现了对应Aware的接口

private void invokeAwareMethods(String beanName, 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);
		}
	}
}

二、InitializingBean接口,afterPropertiesSet,init-method属性调用

初始化的调用又可分为三个步骤:

  • 初始化前置处理:applyBeanPostProcessorsBeforeInitialization()
  • 初始化:afterPropertiesSet,init-method属性调用
  • 初始化后置处理:applyBeanPostProcessorsAfterInitialization()

1.初始化前置处理

【Spring源码学习】Spring Bean实例化过程-创建Bean实例6.2.1节,我们已经完成了@PostConstruct注解扫描,这一步就是调用相关的过程了,依然采用beanPostProcessor调用的方式。当然不止这些注解,还包括Aware接口的调用,ImportAware的支持处理等。

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
		throws BeansException {
	Object result = existingBean;
	//循环处理
	/*
	*着重看这几个:
	* 1.ApplicationContextAwareProcessor 对某个Aware接口方法的调用
	* 2.InitDestroyAnnotationBeanPostProcessor @PostConstruct注解方法的调用
	* 3.ImportAwareBeanPostProcessor 对ImportAware类型实例setImportMetadata 调用(SpringBoot)
	*/
	for (BeanPostProcessor processor : getBeanPostProcessors()) {
		Object current = processor.postProcessBeforeInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}

1.1.Aware接口方法的调用

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
	if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
			bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
			bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
		return bean;
	}
	AccessControlContext acc = null;
	if (System.getSecurityManager() != null) {
		acc = this.applicationContext.getBeanFactory().getAccessControlContext();
	}
	if (acc != null) {
		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
			invokeAwareInterfaces(bean);
			return null;
		}, acc);
	}
	else {
		invokeAwareInterfaces(bean);
	}

	return bean;
}

1.2.@PostConstruct注解方法调用

//InitDestroyAnnotationBeanPostProcessor
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
	LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
	try {
		//调用@PostConstruct注解的方法
		metadata.invokeInitMethods(bean, beanName);
	}
	catch (InvocationTargetException ex) {
		throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
	}
	catch (Throwable ex) {
		throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
	}
	return bean;
}

2.初始化

前置处理完毕,接下来就是InitializingBean 接口和init-method 属性调用过程,实现了InitializingBean 接口的类就必然会调用到afterPropertiesSet 方法,而Init-method 属性调用是在afterPropertiesSet 之后,对应的方法为invokeCustomInitMethod。

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
		throws Throwable {
	//是否是实现了InitializingBean的类
	boolean isInitializingBean = (bean instanceof InitializingBean);
	if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
		if (logger.isTraceEnabled()) {
			logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
		}
		if (System.getSecurityManager() != null) {
			try {
				AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
					((InitializingBean) bean).afterPropertiesSet();
					return null;
				}, getAccessControlContext());
			}
			catch (PrivilegedActionException pae) {
				throw pae.getException();
			}
		}
		else {
			//调用实现了InitializingBean接口的方法
			((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);
		}
	}
}

afterPropertiesSet 和Init-method 和有@PostConstruct 注解的方法其实核心功能都是一样的,只是调用
时序不一样而已,都是在该类实例化和IOC 做完后调用的,我们可以在这些方法中做一些在spring 或者servlet 容器启动的时候的初始化工作。比如缓存预热,比如缓存数据加载到内存,比如配置解析,等等初始化工作调用顺序为先调用@PostConstruct(注解使用)、然后是afterPropertiesSet、InitMethod(xml 配置)方法。

3.初始化后置处理

bean对象初始化后,还会进行一些后置处理,比如后续我们将要重点跟踪的AOP动态代理,这里做个预热。我们先看看动态代理的初始化后置处理是怎样的,看个大概,不做深入讨论。

3.1.代理实例注入

//AbstractAutoProxyCreator
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
	if (bean != null) {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		//上一章节,提到过这个缓存容器,还有印象咩?
		if (this.earlyProxyReferences.remove(cacheKey) != bean) {
			return wrapIfNecessary(bean, beanName, cacheKey);
		}
	}
	return bean;
}

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
		return bean;
	}
	if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
		return bean;
	}
	if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

	//创建当前bean的代理,如果这个bean有advice的话,重点看,重要程度5
	// Create proxy if we have advice.
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
	//如果有切面,则生成该bean的代理
	if (specificInterceptors != DO_NOT_PROXY) {
		this.advisedBeans.put(cacheKey, Boolean.TRUE);
		//把被代理对象bean实例封装到SingletonTargetSource对象中
		Object proxy = createProxy(
				bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
		this.proxyTypes.put(cacheKey, proxy.getClass());
		return proxy;
	}
	this.advisedBeans.put(cacheKey, Boolean.FALSE);
	return bean;
}

bean的创建过程跟玩咯,休息一下,后面简单跟下bean销毁的注册过程。^_^


文章作者: Kezade
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Kezade !
评论
  目录