zoukankan      html  css  js  c++  java
  • Spring源码(1)

    先搭一个框架,简单介绍,以后再补充。

    准备spring环境:

     1 @org.junit.Test
     2     public void test01(){
     3         //把spring所有环境准备好
     4         // 1.准备好DefaultListableBeanFactory
     5         //   实例化一个bdReader和一个Scanner
     6         AnnotationConfigApplicationContext applicationContext =
     7                 new AnnotationConfigApplicationContext();
     8 
     9         //把一个class转成bd,最后put到map
    10         applicationContext.register(AppConfig.class);
    15 
    16         //初始化spring的环境
    17         applicationContext.refresh();
    18 
    19 
    20     }

    构造方法

    进入AnnotationConfigApplicationContext类:

    1.调用AnnotationConfigApplicationContext()构造方法的时候,会先调用父类构造器new出一个工厂DefaultListableBeanFactory。

    1 //new一个工厂DefaultListableBeanFactory
    2     public GenericApplicationContext() {
    3         this.beanFactory = new DefaultListableBeanFactory();
    4     }

     2.初始化一个bean的读取器AnnotatedBeanDefinitionReader和一个扫描器ClassPathBeanDefinitionScanner。

           reader可以读取被加了注解的类,scanner可以扫描所有加了注解的bean。

     1 public AnnotationConfigApplicationContext() {
     2         /**
     3          * 父类的构造方法
     4          * 创建一个读取注解的BeanDefinition读取器
     5          * 什么是bean定义?BeanDefinition
     6          */
     7         //reader能够读取被加了注解的类      this是一个注册器,用来将BeanDefinition转为工厂中的map
     8         this.reader = new AnnotatedBeanDefinitionReader(this);
     9         //可以用来扫描包或者类,继而转换成bd
    10         //但是实际上我们扫描包工作不是scanner这个对象来完成的
    11         //是spring自己new的一个ClassPathBeanDefinitionScanner
    12         //这里的scanner仅仅是为了程序员能够在外部调用AnnotationConfigApplicationContext对象的scan方法
    13         this.scanner = new ClassPathBeanDefinitionScanner(this);
    14     }

     3.进入this.reader = new AnnotatedBeanDefinitionReader(this)方法,一直到: 

    public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
                BeanDefinitionRegistry registry, @Nullable Object source)

           3.1  该方法中首先调用了unwrapDefaultListableBeanFactory()方法,这样获取到工厂。当前的工厂是一个空的工厂,给工厂设置依赖比较器(应该是这样翻译的吧),设置处理延迟加载的功能。

           3.2  设置BeanDefinitionHolder(装的是beanName+BeanDefinition,基本没啥作用,只是为了传参方便,本来传beanName和BeanDefinition,现在传BeanDefinitionHolder就可以)。org.springframework.context.annotation.internalConfigurationAnnotationProcessor

           3.3  将ConfigurationClassPostProcessor,AutowiredAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor,EventListenerMethodProcessor ,DefaultEventListenerFactory 6个

    spring的内置的类转为6个RootBeanDefinition,然后注册器BeanDefinitionRegistry将这些个类注册进工厂,最后这个RootBeanDefinition转换成beanName+BeanDefinition的方式放入BeanDefinitionHolder。

    该registerAnnotationConfigProcessors方法的目的就是将ConfigurationClassPostProcessor类以及其他内置类装入BeanDefinitionHolder,然后返回BeanDefinitionHolder。

    接下来回到2。然后是研究this.scanner = new ClassPathBeanDefinitionScanner(this)。这个scanner的作用基本很小,如果在外部比如调用applicationContext.scan("")方法才会利用到。否则一切的扫描注册和它没有啥关系。

    这样,AnnotationConfigApplicationContext()构造完成。

    注册

    接下来就是注册。进入applicationContext.register(AppConfig.class)方法。

    4.进入doRegisterBean()方法:

     

    (1)先把要注册的bean转为AnnotatedGenericBeanDefinition(AGBD),AnnotatedGenericBeanDefinition包括了bean的其他信息,比如一些元信息,scope,lazy等。

    (2)把类的作用域的名字添加到AGBD中,并且得到注册bean的名字。processCommonDefinitionAnnotations()方法将AGBD中的信息拿出来进行处理,主要处理一些常用的注解,处理完成放回AGBD。

    (3)把AnnotatedGenericBeanDefinition装入BeanDefinitionHolder,然后BeanDefinitionRegistry把BeanDefinitionHolder中的信息(bean)注册进入工厂。

     初始化Spring环境

    5.进入refresh()方法。

    (1)调用prepareRefresh()方法,这是刷新前的准备工作。获取容器的当时时间,同时给容器设置同步标识。

    (2)refresh()-->obtainFreshBeanFactory()-->refreshBeanFactory()获取工厂

    (3)调用prepareBeanFactory(beanFactory):给工厂设置ClassLoader,bean表达式解释器,添加后置处理器beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this))到工厂中的一个list中,在bean实例化的时候在拿出来插手。

    (4)postProcessBeanFactory(beanFactory)

    (5)invokeBeanFactoryPostProcessors(beanFactory),实例化并调用所有已注册BeanFactoryPostProcessor的bean,
    必须在单例bean实例化之前调用。

        ----->invokeBeanFactoryPostProcessors(beanFactory)

                ------->invokeBeanFactoryPostProcessors(beanFactory,getBeanFactoryPostProcessors()):getBeanFactoryPostProcessors()方法获取自己定义的,没有@Component的后置处理器。继续进入invokeBeanFactoryPostProcessors(beanFactory,getBeanFactoryPostProcessors())方法:

               a.判断beanFactory的类型是不是和注册器BeanDefinitionRegistry一个类型。如果是的话,创建两个list,一个是BeanFactoryPostProcessor类型,一个是BeanDefinitionRegistryPostProcessor类型。BeanDefinitionRegistryPostProcessor其实也是继承自BeanFactoryPostProcessor,就是多扩展了一个方法。这两个list都是处理我们自己定义的后置处理器。

               b.建立一个BeanDefinitionRegistryPostProcessor类型的list叫做currentRegistryProcessors,这个list是处理Spring自带的后置处理器,并不是我们定义的,和a中的要有所区分。在3.3中spring已经把自己内部的6个后置处理器放入beanFcatory中了。现在根据BeanDefinitionRegistryPostProcessor取出子类放入currentRegistryProcessors。这样的话,就可以让子类去完成一些事,避免了高度耦合。

               c.把a和b中类型为BeanDefinitionRegistryPostProcessor的list合并,也就是把我们定义的和spring内置的后置处理器放在一块。然后调用invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry)方法,进入方法调用扩展方法postProcessBeanDefinitionRegistry(registry)方法,也就是子类要实现该方法。这也是一个扩展点。目前学到的有三个扩展点:BeanPostProcessor,BeanPostFactoryProcessor,BeanDefinitionRegistryPostProcessor。BeanDefinitionRegistryPostProcessor继承自BeanPostFactoryProcessor,但是又在BeanPostFactoryProcessor的基础上进行了扩展。

               d.接着c讲,BeanDefinitionRegistryPostProcessor的子类ConfigurationClassPostProcessor实现了postProcessBeanDefinitionRegistry(registry)方法,进入方法,调用了processConfigBeanDefinitions(registry)方法。在这个方法中,取出工厂中所有的BeanDefinition,包括自定义的以及spring内置的。从每一个BeanDefinition获取到原始bean的元信息,判断bean是不是加了@Configuration注解。如果是,加入到BeanDefinitionHolder的list中,如果不是,再继续判断是否加了@Component,@ComponentScan,@Import,@ImportResource这些注解,如果是,同样加入到BeanDefinitionHolder的list中。接下来就是解析这些加了注解的类。调用parser.parse(candidates)方法进行解析。parse方法中调用了另外的parse(AnnotationMetadata,beanName)方法来进行解析。继续调用processConfigurationClass()方法,继续调用doProcessConfigurationClass()方法,在该方法中,处理@ComponentScan的信息。调用this.componentScanParser.parse()方法,该方法中定义了一个ClassPathBeanDefinitionScanner作为扫描器,继续调用scanner.doScan()方法,这个方法是很重要的方法,用来扫描包。首先定义一个BeanDefinitionHolder,负责装扫描出来的BeanDefinition。调用findCandidateComponents(basePackages)方法,扫描basePackage路径下的java文件,符合条件的并把它转成BeanDefinition类型。调用scanCandidateComponents(String basePackage)方法,把.class文件扫描出来。

  • 相关阅读:
    PHP编译安装
    PHP编译安装
    Apache编译安装
    Apache编译安装
    端口号
    端口号
    初步理解TCP/IP网络
    初步理解TCP/IP网络
    剑指offer——树的子结构
    STL四种智能指针
  • 原文地址:https://www.cnblogs.com/xp1234/p/12555448.html
Copyright © 2011-2022 走看看