作者:天天火火红红 | 来源:互联网 | 2023-09-23 18:24
前面已经分析过BeanDefinition在IoC容器中载入和解析的过程。在这些动作完成以后,用户定义的BeanDefinition信息已经在IoC容器内建立了自己的
前面已经分析过BeanDefinition在IoC容器中载入和解析的过程。在这些动作完成以后,用户定义的BeanDefinition信息已经在IoC容器内建立了自己的数据结构 以及相应的数据表示,但此时这些数据还不能该提供IoC容器更友好的使用方式,在DefaultListableBeanFactory中,是通过一个HashMap来持有载入的BeanDefinition的,这个HashMap的定义在DefaultListableBeanFactory中可以看到,如下所示:
/** Map of bean definition objects, keyed by bean name. */private final Map beanDefinitiOnMap= new ConcurrentHashMap<>(256);
将解析得到的BeanDefinition向IoC容器中的beanDefinitionMap注册的过程是在载入BeanDefinition完成后进行的,注册的调用过程为:
我们跟踪以上的代码调用去看一下具体的注册实现,在DefaultListableBeanFactory中实现了BeanDefinitionRegistry的接口,这个接口的实现完成BeanDefinition向容器的注册。这个注册过程并不复杂,就是把解析得到的BeanDefinition设置到hashMap中去。需要注意的是到同名的BeanDefinition,进行处理的时候需要依据allowBeanDefinitionOverriding的配置来完成。
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException {Assert.hasText(beanName, "Bean name must not be empty");Assert.notNull(beanDefinition, "BeanDefinition must not be null");if (beanDefinition instanceof AbstractBeanDefinition) {try {((AbstractBeanDefinition) beanDefinition).validate();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,"Validation of bean definition failed", ex);}}// 这里检查是不是有相同名字的BeanDefinition已经在IoC容器中注册了,如果有相同名字的BeanDefinition,但又不允许覆盖,那么会抛出异常BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);if (existingDefinition != null) {if (!isAllowBeanDefinitionOverriding()) {throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);}else if (existingDefinition.getRole() updatedDefinitiOns= new ArrayList<>(this.beanDefinitionNames.size() + 1);updatedDefinitions.addAll(this.beanDefinitionNames);updatedDefinitions.add(beanName);this.beanDefinitiOnNames= updatedDefinitions;removeManualSingletonName(beanName);}}// 这是正常注册BeanDefinition的过程,把Bean的名字存入到beanDefinitionNames的同时,把beanName作为Map的key,把beanDefinition作为value存入到IoC容器持有的beanDefinitionMap中去else {// Still in startup registration phasethis.beanDefinitionMap.put(beanName, beanDefinition);this.beanDefinitionNames.add(beanName);removeManualSingletonName(beanName);}this.frozenBeanDefinitiOnNames= null;}if (existingDefinition != null || containsSingleton(beanName)) {resetBeanDefinition(beanName);}else if (isConfigurationFrozen()) {clearByTypeCache();}}
完成了BeanDefinition的注册,就完成了IoC容器的初始化过程。此时,在使用的IoC容器DefaultListableBeanFactory中已经建立了整个Bean的配置信息,而且这些BeanDefinition已经可以被容器使用了,它们都在beanDefinitionMap里被检索和使用。容器的作用就是对这些信息进行处理和维护。这些信息是容器建立依赖反转的基础,有了这些基础数据,下面我们看一下在IoC容器中,依赖注入是怎样完成的。