深入理解 Spring finishBeanFactoryInitialization

上篇博文中我们看到了将Spring环境中的 BeanPostProcessor找出来,添加到BeanFactory中的beanPostProcessors中,统一维护,本片博文继续往下拓展,看下Spring如何实例化bean,以及如何实现在bean的实例化通过各种各样的后置处理器完成bean的增强

所以本次的程序入口是AbstractApplicationContext中的finishBeanFactoryInitialization(beanFactory);,源码如下,主要做了如下几件事

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // Initialize conversion service for this context. // 为上下文初始化类型转换器 if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } // 检查上下文中是否存在类型转换器 if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); } // 尽早初始化LoadTimeWeaverAware bean,以便尽早注册它们的转换器。 // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early. String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } // Stop using the temporary ClassLoader for type matching. // 禁止使用临时类加载器进行类型匹配 beanFactory.setTempClassLoader(null); // Allow for caching all bean definition metadata, not expecting further changes // 允许缓存所有的bean的定义数据 beanFactory.freezeConfiguration(); // Instantiate all remaining (non-lazy-init) singletons. // 准备实例化bean beanFactory.preInstantiateSingletons(); }

我们着重看他是如何创建实例化bean的,跟进beanFactory.preInstantiateSingletons();,调用beanFactory的方法准备实例化bean, 这个beanFactory就是Spring默认是bean工厂, DefaultListableBeanFactory, 源码如下:方法不算很长,逻辑也很清楚, 一开始Spring取出当前上下文中所有的BeanName列表,因为在执行到这里之前,已经完成包扫描了所以说这个盛放beanName的list里面存放的就是所有的需要实例化的对象的全集,包含Spring自己的,和程序员自己添加的还包含Aspectj的

所以说,当前方法的目标很明了,就是遍历这个list中的每一个beanName,然后实例化当前beanName相应的bean

当然,如果想实例化,前提是不能是抽象类,不能是接口,非懒加载, 而且针对FactoryBean还有不同的处理模式

public void preInstantiateSingletons() throws BeansException { if (logger.isDebugEnabled()) { logger.debug("Pre-instantiating singletons in " + this); } //所有bean的名字 // Iterate over a copy to allow for init methods which in turn register new bean definitions. // While this may not be part of the regular factory bootstrap, it does otherwise work fine. //todo 遍历一个副本以允许init方法,而init方法反过来注册新的bean定义。 // todo 盛放所有的beanName,所有的需要实例化的beanName都在这里,包括Spring断断续续添加的, Aspectj的, 程序员通过注解标识的 List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans... // todo 触发所有非延迟加载单例beans的初始化,主要步骤为调用getBean for (String beanName : beanNames) { // todo 合并父类BeanDefinition,可以进入查看 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); //todo 三个条件,抽象,单例,非懒加载 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); // todo 如果是FactoryBean则加上& // todo 检验是否是 FactoryBean 类型的对象 if (bean instanceof FactoryBean) { final FactoryBean<?> factory = (FactoryBean<?>) bean; boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } } else { // todo 因为我们没有添加FactoryBean类型的对象, 一般都会进入这个getBean getBean(beanName); } } }

下面接着跟进getBean(beanName);方法,顾名思义获取Bean,再往下跟下去,就算是本文的正文开始部分了,但是我想在这里提醒自己,一个比较有分量的剧透吧,当前的getBean(beanName)它是有返回值的,一会当我们往下跟进的是时候会发现会存在递归的现象,这一点巧妙的实现了@Autowired处理setter方式实现循环引用

ok,现在继续看代码,经过了几个空方法的传递,我们来到下面的代码中,它主要做了如下几件事

首先将传递进来的name转换成了beanName

原因1: FactoryBean的实现类的存储方式和其他的类完全相同,添加上&是获取不到的, 因此我们将&去掉 原因2: 解决别名的问题

为什么在创建bean之前先调用getSingleton()?

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwpfgs.html