Spring源码阅读

Spring源码阅读

  • ApplicationContext(应用上下文)
  • AnnotationConfigApplicationContext做了什么?
    • this()
    • register(@Configuration的类 下面用配置类代替)
    • refresh
      • 准备阶段
      • 开始做事
  • 总结

事实上我不太愿意写源码类文章,我估计我发的源码文章也就这一次了吧。因为事实上读源码是一件很浪费时间的事,毕竟不是所有人都愿意读源码,这种文章看的人也不会很多,写起来也费事。

ApplicationContext(应用上下文)

我们知道,IOC容器是通过反射来管理所有的对象,通过谁呢?事实上就是通过这个上下文,起到承上启下的作用。

  • ClassPathXmlApplicationContext
    通过Xml文件解析应用上下文配置
    继承了AbstractXmlApplicationContext,同样继承AbstractXmlApplicationContext的还有FileSystemXmlApplicationContext
  • AnnotationConfigApplicationContext
    通过注解类解析应用上下文配置

AnnotationConfigApplicationContext做了什么?

当new一个AnnotationConfigApplicationContext,并且传入了@Configuration的类后,它的构造函数会运行this()构造函数register(annotatedClasses)refresh()。顾名思义,就是进行了注册和刷新。

this()

调用默认构造函数做了哪些事呢?

  1. this.reader = new AnnotatedBeanDefinitionReader(this);
    在AnnotatedBeanDefinitionReader的构造函数中会初始化环境变量(如果存在则不创建,如果不存在就new 一个StandardEnvironment),
  2. this.scanner = new ClassPathBeanDefinitionScanner(this);
    在ClassPathBeanDefinitionScanner的构造函数中同样会初始化环境变量(和上面一个操作)

创建了一个BeanDefinition的reader和一个BeanDefinition的scanner。下面的register会用到这个reader,至于scanner,后面会讲。

BeanDefinition 是什么?
中文直译Bean定义,既然如此肯定是存着Bean的一些信息呗,BeanDefinition当中存储着bean的scope,className,是否懒加载,Primary,FactoryBeanName,FactoryMethodName,DependsOn(依赖谁)等等信息。

register(@Configuration的类 下面用配置类代替)

register的实参就是 new AnnotationConfigApplicationContext时传的实参,那么它做了什么事呢?
它调用了默认构造函数中创建的AnnotatedBeanDefinitionReader也就是this.readerregister方法,参数保持不变。然后又包装了一层调用doRegisterBean,同样参数不变。

doRegisterBean做了什么:

  1. AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
    AnnotatedGenericBeanDefinition的构造函数中将会设置beanClass为传进来的配置类
    然后执行this.metadata = new StandardAnnotationMetadata(beanClass, true);顾明思议,这是在创建元数据了,其中第二个参数的含义是是否嵌套为Map.
    metadata 中有什么东西呢?
    它会获取传进来的配置类中的注解,metadata 默认是一个列表。至于第二个参数含义上面有说。

  2. 判断this.conditionEvaluator.shouldSkip(abd.getMetadata())
    还记得metadata中有什么吧,有配置类的所有注解信息,和introspectedClass 也就是配置类,shouldSkip做的就是去通过所有的注解信息判断有没有@Conditional注解,springboot中的自动配置里有很多,用来判断到底要不要生成这个bean.

在下面就是去解析abd 的元数据等等,里面包含了abd中beanClass(也就是配置类)的scope和代理方式的信息(是abd自己的信息,不是metadata里所有的注解信息)。然后通过BeanDefinitionReaderUtils.registerBeanDefinition将配置类当做Bean注册到ApplicationContext中。

记住它做的最重要的2个事即可,生成配置类的BeanDifinition注册配置类的BeanDefinition到ApplicationContext中

refresh

准备阶段

  1. prepareRefresh();
    预处理阶段,也就是准备工作,记录启动时间,设置上下开关标志,初始化PropertySources,earlyApplicationEvents等等。

  2. beanFactory = obtainFreshBeanFactory();
    获取新的beanFactory下面会用到
    beanFactory 中最重要的就是beanDefinitionMapbeanDefinitionNames了,里面记录了所有的BeanDefinition信息.

  3. prepareBeanFactory(beanFactory);
    预处理beanFactory,就是为刚才获取到的新的beanFactory设置classLoader,spel解析器等等

开始做事

  1. postProcessBeanFactory(beanFactory);
    直译就是后置处理,做什么呢?
    当所有BeanDefinition都被加载(注意此时还有进行实例化),会调用这个方法。
    源码注释中的意思是你可以自己写一个BeanFactory的后置处理器。

  2. invokeBeanFactoryPostProcessors(beanFactory);
    实例化并调用所有注册的后置处理器(实现BeanFactoryPostProcessor的bean和DefaultListableBeanFactory)。

    invokeBeanFactoryPostProcessors 运行时,beanFactory的beanDefinitionMap中还没有我们自己@Bean的BeanDefinition信息,只有配置类和spring内置Bean的BeanDefinition的信息。在执行完invokeBeanFactoryPostProcessors方法中的invokeBeanDefinitionRegistryPostProcessors后,才会有我们自己@Bean或@Componentscan扫描到的信息。
    invokeBeanDefinitionRegistryPostProcessors 中会遍历postProcessor,通过ConfigurationClassPostProcessor进行解析配置类信息。

  3. registerBeanPostProcessors(beanFactory);
    注册后置处理器的bean(注意:不是BeanFactoryPostProcessor的beanBeanPostProcessor

  4. initMessageSource();
    初始化国际化资源(多语言的一些信息)

  5. initApplicationEventMulticaster();
    初始化事件多播器

  6. onRefresh();
    和postProcessBeanFactory类似,也是模板方法,可以自己实现功能,用于上下文的刷新工作

  7. registerListeners();
    注册监听器

  8. finishBeanFactoryInitialization(beanFactory);
    实例化所有需要处理的(非懒加载)单例bean。

    其中会调用beanFactory.preInstantiateSingletons
    这时候就会获取beanDefinitionNames这个列表进行遍历。然后去判断他是否是抽象类,单例模式,懒加载等
    if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit())
    还会判断isFactoryBean,如果是则通过singletonObjects(一个map)尝试获取Bean.
    如果isFactoryBean为假,就是我们自己的@Bean了,这时候会通过getBean->doGetBean->getSingleton来创建实例。

    getSingleton 有好几个重载方法,默认调用的是getSingleton(String beanName) 他会调用到下面这个重载方法,并且allowEarlyReference为true,这个主要是为了解决循环引用问题,共有3个缓存

    • singletonObjects
    • singletonFactories
    • earlySingletonObjects
      什么情况下会用到呢?比如A对象用到了B对象,B对象又用到了A对象,这时候其中一个对象就会被缓存在earlySingletonObjects这个map中。
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
           
        // 先从单例缓存中找,没有找到会 判断是否是正在创建的bean
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
           
        	//如果是 上锁
            synchronized (this.singletonObjects) {
           
                // 尝试从earlySingletonObjects中找
                singletonObject = this.earlySingletonObjects.get(beanName);
                // earlySingletonObjects也没找到 就判断是否应该创建早期引用
                if (singletonObject == null && allowEarlyReference) {
           
                	// 获取beanName对应的单例工厂
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
           
                        //创建bean,并缓存,用于解决循环依赖
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }
    

    默认情况下上面那段代码肯定是获取不到bean的,因为缓存里根本没有,所以会继续在doGetBean往下走

    	sharedInstance = getSingleton(beanName, () -> {
           
    		try {
           
    			return createBean(beanName, mbd, args);
    		}
    		catch (BeansException ex) {
           
    			// Explicitly remove instance from singleton cache: It might have been put there
    			// eagerly by the creation process, to allow for circular reference resolution.
    			// Also remove any beans that received a temporary reference to the bean.
    			destroySingleton(beanName);
    			throw ex;
    		}
    	});
    

    可以看见这次调用了getSingleton(String beanName, ObjectFactory singletonFactory)的重载方法,通过createBean创建bean.并且在创建后,如果是新创建的,将调用addSingleton将实例添加到singletonObjects这个map

  9. finishRefresh();
    清理资源缓存(扫描到的上下文中ASM的元数据)
    初始化生命周期处理器
    获取生命周期处理器并执行onRefresh方法
    发送结束事件
    加入bean视图(JMX相关)

最后 清除公共缓存

总结

我们清楚的知道,在register中注册了我们的配置类信息。真正重要的地方在refreshinvokeBeanFactoryPostProcessorsfinishBeanFactoryInitialization
单例Bean在创建后会在singletonObjects这个map中有缓存

beanDefinitionMap和beanDefinitionNames 存着BeanDefinition的Map和列表

BeanDefinition存着的是Bean的scope,className,是否懒加载,Primary,FactoryBeanName,FactoryMethodName,DependsOn(依赖谁)等等信息

你可能感兴趣的:(Java)