博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringBoot源码学习(三)
阅读量:4210 次
发布时间:2019-05-26

本文共 8386 字,大约阅读时间需要 27 分钟。

我们说在springApplication类中中的prepareContext方法中将我们的启动类注册到了spring容器中。当时分析的在loader.load()方法中.那么这个方法又是怎么做的。根据正常的想法我们知道如果拿到了启动类那么就拿到了启动类上边的注解,而启动类上边的注解就包含了太多的信息。通过这些信息就可以将项目所需要的类全部注册到BeanDefinitionLoader中,但是前提是我们要多这个类有所了解。才能逐步去跟进我们的猜想。

打开源码之后,发现这个类提供的方法不多,但是相关的类比较多。

那么咋看看这些类大概都是做什么的

private final Object[] sources;    //解析注解的bean    private final AnnotatedBeanDefinitionReader annotatedReader;    //注册xml中的bean    private final XmlBeanDefinitionReader xmlReader;    private BeanDefinitionReader groovyReader;    //传入的是包路径    private final ClassPathBeanDefinitionScanner scanner;    private ResourceLoader resourceLoader;

大概得想法就是这样,那么程序中是怎么做的?我们详细看一些其提供的各种load方法、

    //根据类型判断采用那种方式进行load    private int load(Object source) {        Assert.notNull(source, "Source must not be null");        if (source instanceof Class) {        //传入的是类            return this.load((Class)source);        } else if (source instanceof Resource) {            return this.load((Resource)source);        } else if (source instanceof Package) {            return this.load((Package)source);        } else if (source instanceof CharSequence) {            return this.load((CharSequence)source);        } else {            throw new IllegalArgumentException("Invalid source type " + source.getClass());        }    }
    //如果传入的是类,那么就用 annotatedReader注册     private int load(Class
source) { if (this.isGroovyPresent() && BeanDefinitionLoader.GroovyBeanDefinitionSource.class.isAssignableFrom(source)) { BeanDefinitionLoader.GroovyBeanDefinitionSource loader = (BeanDefinitionLoader.GroovyBeanDefinitionSource)BeanUtils.instantiateClass(source, BeanDefinitionLoader.GroovyBeanDefinitionSource.class); this.load(loader); } if (this.isComponent(source)) { this.annotatedReader.register(new Class[]{source}); return 1; } else { return 0; } }

其他方法类似。这里不在赘述。我们继续跟踪我们的load方法。

通过查看annotationConfigServletWebServerApplicationContext类的继承关系图,我们发现其本质上有BeanDefinitionLoader身影。

而在GenericApplicationContext我们又发现了BeanFactory,因此也就是说

annotationConfigServletWebServerApplicationContext已经包含了一切。

了解了这些,我们从prepareContext中开始寻找load的真谛。

我们看到在prepareContext中BeanDefinitionLoader,其中的rources就是我们的启动了,registry就是我们的annotationConfigServletWebServerApplicationContext。但是我们在springApplication中就已经通过createApplicationContent创建了BeanDefinitionLoader,这里为啥要重新创建?

protected BeanDefinitionLoader createBeanDefinitionLoader(BeanDefinitionRegistry registry, Object[] sources) {        return new BeanDefinitionLoader(registry, sources);    }
protected void load(ApplicationContext context, Object[] sources) {        if (logger.isDebugEnabled()) {            logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));        }        BeanDefinitionLoader loader = this.createBeanDefinitionLoader(this.getBeanDefinitionRegistry(context), sources);        if (this.beanNameGenerator != null) {            loader.setBeanNameGenerator(this.beanNameGenerator);        }        if (this.resourceLoader != null) {            loader.setResourceLoader(this.resourceLoader);        }        if (this.environment != null) {            loader.setEnvironment(this.environment);        }        loader.load();    }

看样子是要做一下处理了。我们看到这里的loader其实是new出来的,并不是从content中拿取的,因为我们最终还是要将bean注册到content中的beanfactory中,因此看的出来,这里采用new的方式更像是被看做工具。因为并不会影响content中注册的bean的最终目的。

我们进去laod方法

public int load() {        int count = 0;        //这里的resource就是我们上边createBeanDefinitionLoader方法传入的        //启动类        Object[] var2 = this.sources;        int var3 = var2.length;        for(int var4 = 0; var4 < var3; ++var4) {            Object source = var2[var4];            count += this.load(source);        }        return count;    }

我们看看这里的this.load(source);正好就是咋那会儿看的根据不同类型的传入参数进行不同的load方法。

显然我们传入的是class。那么我们就进入第一个方法。

这块采用的注解的reader进行注册。

为了更好的理解这个reader,我们有必要看一下他的初始化方法。看到最后发现了很长的一段代码。我们就传入了content,没想到居然有那么复杂的逻辑。那么这块到底是干啥的?看着这么多的代码有没有感到恐惧。

public static Set
registerAnnotationConfigProcessors(      BeanDefinitionRegistry registry, @Nullable Object source) {      //从content中获取beanfactory DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); if (beanFactory != null) { if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) { //设置依赖比较器,解析@Order和@Priority beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); } if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {        //设置bean的@Autowired解析器 beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); } } Set
beanDefs = new LinkedHashSet<>(8);    //如果我们的content中没有包含 ConfigurationClassPostProcessor那就注册到content中 //这里的ConfigurationClassPostProcessor是一个后置处理器 if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); }//如果没有AutowiredAnnotationBeanPostProcessor处理器,那就注册进去 if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); }//注册CommonAnnotationBeanPostProcessor // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor. if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)); }// // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor. if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(); try { def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, AnnotationConfigUtils.class.getClassLoader())); } catch (ClassNotFoundException ex) { throw new IllegalStateException( "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex); } def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)); }//EventListenerMethodProcessor的注册 if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME)); } if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));    } return beanDefs; }

通过上述的代码详解,我们发现初始化AnnotatedBeanDefinitionReader的时候居然做了那么多工作。但是这里有一个特别重要的概念:后置处理器。

我们看看它怎么工作的

我们来手动实现一个,然后看看有什么蛛丝马迹

@Componentpublic class MyAppTest implements BeanDefinitionRegistryPostProcessor {    @Override    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {        System.out.println("注册bean");        //这里的BeanDefinitionRegistry应该就是content    }    @Override    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {        //这里就是bean工厂        System.out.println("这里是工厂");    }}

启动测试项目

发现实现了该接口的方法的类,会在bean容器加载结束,bean实例化之前进行调用。那么如果定义多个这样的类是不是会每个都执行一下?咋继续测试一下。发现还真实这么一回事。那么就好理解上边哪些后置处理器了。因为我们可以看到在这个接口的入参都是重量级元素,那可是可以轻松的获取所有bean的呀,所以相当于说可以对其进行各种操作。上边注册的哪些后置处理器其实就是用来解析的。解析结束之后就可以实例化了。是不是发现这个接口非常好?我目前是这样想的。但是至于在哪里去掉这个接口,我想应该在我们之前分析的那个核心方法中。就是refresh中。这个后期咋再突破。

看的出来,这个loader.load()目前来说就只把启动类注册到了content中了。那么其他的类是在那块逻辑中会被注册进来?我想是在那些后置处理器中。

转载地址:http://aqkmi.baihongyu.com/

你可能感兴趣的文章
Linux系统时间与RTC时间
查看>>
TF卡和SD卡理解
查看>>
在 Java 中应用设计模式 - Factory Method .
查看>>
Linux Kernel Boot CMDLINE Processing
查看>>
字符杂项设备(miscdevice)
查看>>
bootloader-bootable解析
查看>>
bootloader (LK)&&android lk bootloader中相关修改指南
查看>>
SD卡驱动分析--基于高通平台
查看>>
SD Card 驱动流程分析
查看>>
Linux之debugfs介绍
查看>>
Linux DebugFS 子目录也是用debugfs_create_dir来实现
查看>>
关于sd卡中一些概念的理解
查看>>
SD卡图形介绍
查看>>
linux MISC 驱动模型分析
查看>>
马达 vibrator的android的timed_output实现方式
查看>>
linux kernel panic解决思路
查看>>
定位Oops的具体代码行分析死机日志的方法
查看>>
Linux kernel oops panic 调试技巧
查看>>
sd是否在位检查
查看>>
关于USB Gadget开发
查看>>