上一篇介绍了加载bean的一种特殊方法,这篇我们就来聊一聊正常加载bean的方式。
还是分步走,忽略一些部分,聚焦到整体流程。
instanceWrapper = createBeanInstance(beanName, mbd, args);
这方法的内部代码非常长,而且对我来说有点晦涩。相比于其它部分,它显得并不是那么重要。
这里我就简单总结总结一下,有兴趣的同学可以自行研究一下。
BeanDefinition
中的supplier属性,则通过supplier.get()方法获取BeanWrapper。BeanDefinition
中的factoryMethodName,这通过另一种方式获取。(这里并没有深入研究)找到所有实现了MergedBeanDefinitionPostProcessor
的实例 ,然后访问其postProcessMergedBeanDefinition()
方法。
这里主要是为了后面填充Bean属性做一些前置准备。
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//列举2个有感觉的
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
比如说 @Autowrited
,@Value
, @Resource
, @Lazy
等的前置处理工作就是在这个节点上触发的。
这一步主要是处理循环依赖,同时也为我们提供了一个解决方案的切入口。
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//添加循环依赖的解决方案
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
这个getEarlyBeanReference()
方法的触发节点就在最最上面,我们通过getSingloten()
获取单例的时候,如果从beanFactory中没有找到,那么就会通过实现了SmartInstantiationAwareBeanPostProcessor
接口实例的getEarlyBeanReference()
方法中获得。
从这里可以看到BeanDefinition中的属性填充优先级是最高的,其次是个各个处理器。
//判断bean是否需要创建
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//如果返回false则跳过属性填充逻辑
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
主要是寻找所有实现了InstantiationAwareBeanPostProcessor
的实例,并访问其postProcessAfterInstantiation()
方法,如果返回的是false这跳过属性填充逻辑。
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;
}
}
这里其实按照思路来看应该是通过InstantiationAwareBeanPostProcessor
实例的 postProcessProperties()
方法 或 postProcessPropertyValues()
方法来获取PropertyValues 为后续的填充属性做准备。
但是,我在往里面继续查看的时候发现了很多处理器都是通过前置的反射直接对bean的属性进行赋值。 这个是个疑问点吧。感兴趣的同学可以自行研究一下,如果你有什么好想法,欢迎私信我 或在下方留言。
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
内部逻辑就不详细聊了。需要注意的是,它的填充方式是通过访问属性set方法,所以需要你保证必须有属性对应的set方法才行。(难道就是因为这个局限性?上面的处理方式是通过反射)
到此填充属性就完毕了。
通过名字翻译过来确实是初始化bean,但给我的感觉它更像是,完结的通知,触发一个个的扩展节点。
因为在上面Bean已经实例化了,并且属性也注入完毕了,剩下的可不就只剩通知扩展节点了嘛。
我将它理解为4类通知,分别是:
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);
}
}
}
包含了三种,BeanNameAware
,BeanClassLoaderAware
,BeanFactoryAware
。
BeanNameAware
:创建完毕的Bean 名称通知
BeanClassLoaderAware
:加载Bean的classLoader 通知
BeanFactoryAware
:加载Bean的BeanFactory 通知
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
包含了一种,实现了BeanPostProcessor
实例的postProcessBeforeInitialization()
方法
其中又包含一个特例,如果有同学了解过Bean初始化的几种手段的话,应该知道一个注解@PostConstruct
这种初始化的手段是在前置通知中完成的。实现类是CommonAnnotationBeanPostProcessor
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
//第一种
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))){
((InitializingBean) bean).afterPropertiesSet()
}
}
//第二种
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
invokeCustomInitMethod(beanName, bean, mbd);
}
初始化通知包含两种
InitializingBean
接口initMethodName
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
包含一种,实现了BeanPostProcessor
实例的 postProcessAfterInitialization()
方法。
这里存在很多限制,也会引发一些问题。具体详情我将另开一章单独讲解。
其实就是看下bean是否实现了DisposableBean接口,如果有,等bean销毁的时候调用其方法。