spring IOC原理之:BeanDefinition
接下来将用3篇文章介绍spring IOC控制反转的简要流程,第一篇先来了解下BeanDefinition。
1. BeanDefinition是什么?
BeanDefinition是一个接口,有很多属性:类名、scope、属性、构造函数参数列表、是否是单例类、是否是懒加载等,spring将bean信息赋予BeanDefifition,实际场景使用的是RootBeanDefinition,GenericBeanDefinition,AnnotatedGenericBeanDefinition等实现类。
2. BeanDefinition从哪里来?
BeanDefinition通过解析注入bean的类信息得来。例如,ApplicationContex的实现类AnnotationConfigServletWebServerApplicationContext类就定义了reader和scanner来解析注入的bean,它们会解析例如@Component注解的bean:

首先我们需要扫描被@Component注解的bean,然后才能解析成BeanDefinition。这些工作是由AnnotatedBeanDefinitionReader#doRegisterBean方法和ClassPathBeanDefinitionScanner#doScan方法共同完成的。过程如下:
AnnotationConfigServletWebServerApplicationContext#postProcessBeanFactory

AnnotatedBeanDefinitionReader#doRegisterBean

ClassPathBeanDefinitionScanner#doScan

3. BeanDefinition封装好了要到哪里去?
BeanDefinition封装好了之后,紧接着被封装成了BeanDefinitionHolder,接着调用了BeanDefinitionReaderUtils.registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)方法:

BeanDefinitionReaderUtils#registerBeanDefinition方法做了2件事:
1.用BeanDefinitionRegistry#registerBeanDefinition方法以primary name的方式注册BeanDefinition;
2.用BeanDefinitionRegistry#registerAlias方法以aliases name的方式注册BeanDefinition;
那么BeanDefinitionRegistry是啥?BeanDefinitionRegistry是一个接口,spring上下文类会实现该接口,AnnotationConfigServletWebServerApplicationContext也实现了该接口:

具体的实现在DefaultListableBeanFactory#registerBeanDefinition方法,BeanDefinition对象被放入beanDefinitionMap中:

BeanDefinitionReaderUtils#registerBeanDefinition方法中的入参BeanDefinitionRegistry registry就是spring上下文类实例,也就是说BeanDefinition封装后放到了spring上下文类中:

俗话说:边看代码边debug,神仙代码也不怕!让我们断点看看。在registerBeanDefinition方法断点,可以看到apiAspect实例的BeanDefinition被put到beanDefinitionMap中(被注册到IOC容器中):

现在我们已经对BeanDefinition有了充分的了解,那么就模拟手动注册一个BeanDefinition到spring上下文中。
1.首先让一个@Component的类实现BeanFactoryAware接口,实现setBeanFactory方法,从而获取beanFactory;
2.然后调用registerBeanDefinition方法将Dog.class的BeanDefinition注册进去;

3.从spring上下文中获取Dog.class的实例,可以看到“旺财”已经被注入进去了,安排!