spring初始化&循环引用

一、寻找核心方法

// == 入口 public static void main(String[] args) { SpringApplication.run(SpringRunner.class, args); }// == 调用链 org.springframework.boot.SpringApplication#run(java.lang.Class, java.lang.String...) org.springframework.boot.SpringApplication#run(java.lang.Class[], java.lang.String[]) org.springframework.boot.SpringApplication#run(java.lang.String...) org.springframework.boot.SpringApplication#refreshContext org.springframework.boot.SpringApplication#refresh

【spring初始化&循环引用】记住refresh方法,它非常重要
观察它的内部实现:
// ##### IOC容器初始化 ##### // 告知子类要初始化BeanFactory // BeanDefinition信息的读取是在子类的refreshBeanFactory()方法里完成的 ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); // 准备bean工厂以在此上下文中使用。 this.prepareBeanFactory(beanFactory); // ##### 著名的九大方法 ##### try { // 设置beanFactory的后置处理 postProcessBeanFactory(beanFactory); // 调用beanFactory的后置处理,如springboot自动装配获取配置的Entity invokeBeanFactoryPostProcessors(beanFactory); // 注册beanFactory的后置处理 registerBeanPostProcessors(beanFactory); // 初始化上下文的消息 initMessageSource(); // 初始化上下的事件 initApplicationEventMulticaster(); // 初始化一些特殊的bean onRefresh(); // 检查一些监听的bean并注册到容器中 registerListeners(); // Instantiate all remaining (non-lazy-init) singletons,spring bean对象初始化在这里 finishBeanFactoryInitialization(beanFactory); // 发布容器事件,结束Refresh过程 finishRefresh();

二、注册和扫描 本节深入分析构建BeanFactory的过程。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // == 调用链 org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory // -- 分析注解方式注入 org.springframework.web.context.support.AnnotationConfigWebApplicationContext#loadBeanDefinitions

1.向容器注册对象信息 注入的本质就是向容器(也有叫上下文的,就是Context的直译)——实质就是一个Map注册类的描述信息。
用代码描述就是:
beanDefinitionMap.put(BeanDefinition)
看看具体实现:
// == 注册逻辑 protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) { AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory); if (!this.annotatedClasses.isEmpty()) { reader.register(this.annotatedClasses.toArray(new Class[this.annotatedClasses.size()])); } }// == 调用链 org.springframework.context.annotation.AnnotatedBeanDefinitionReader#register org.springframework.context.annotation.AnnotatedBeanDefinitionReader#registerBean(java.lang.Class) org.springframework.context.annotation.AnnotatedBeanDefinitionReader#doRegisterBean

这个方法值得细说一下:
void doRegisterBean(Class annotatedClass, @Nullable Supplier instanceSupplier, @Nullable String name, @Nullable Class[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {//## 被注解修饰的对象,会被封装成BeanDefinition结构 AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass); //为注解Bean定义生成Bean名称 String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); // BeanDefinition再次封装 BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); // ## 注入 BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); }// == 调用链 org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerBeanDefinition // -- 前面创建的工厂是DefaultListableBeanFactory org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition

最终的注入逻辑:
// 存储注册信息的BeanDefinition private final Map beanDefinitionMap = new ConcurrentHashMap<>(256); public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { // ## 注入的本质 this.beanDefinitionMap.put(beanName, beanDefinition); }

2.扫描指定package的配置信息 无它,只为扩大扫描范围。
默认只注入SpringRunner(Starter类)的子包
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) { //为容器设置类路径Bean定义扫描器 ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory); if (!this.basePackages.isEmpty()) { scanner.scan(this.basePackages.toArray(new String[this.basePackages.size()])); } }// == 调用链 org.springframework.context.annotation.ClassPathBeanDefinitionScanner#scan org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScanprotected Set doScan(String... basePackages) { //遍历扫描所有给定的包 for (String basePackage : basePackages) { // ## 同样执行注入流程 registerBeanDefinition(definitionHolder, this.registry); } }

未完待续(懒癌发作……)

    推荐阅读