上一章讲完了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销毁的注册过程。^_^