美文网首页
Spring Bean 基础

Spring Bean 基础

作者: Tinyspot | 来源:发表于2022-07-09 09:03 被阅读0次

    1. Bean 类型

    • 普通 Bean
    • 工厂 Bean

    1.1 Spring bean VS Java bean

    • Spring bean 有一个初始化的过程,经历过完整 Spring 生命周期,放在spring 容器里
    • Java bean 是 new 出来的对象

    1.2 回调注入

    • Aware 接口
    • ApplicationContextAware

    ApplicationContextAware

    • 回调注入 ApplicationContext

    2. Spring bean 的生命周期

    • Spring 会将 class 信息封装成 BeanDefinition,然后再放进 DefaultListableBeanFactory 的beanDefinitionMap中

    2.1 BeanDefinition

    • BeanDefinition 是一种配置元信息,它描述了 Bean 的定义信息
    • interface BeanDefinition extends AttributeAccessor, BeanMetadataElement
    • AbstractBeanDefinition 的三个子类
      • GenericBeanDefinition
      • RootBeanDefinition
      • ChildBeanDefinition

    源码分析

    • 入口 obtainFreshBeanFactory()
    • refreshBeanFactory()
    • loadBeanDefinitions(beanFactory);
    • loadBeanDefinitions(beanDefinitionReader);
    • doLoadBeanDefinitions(inputSource, encodedResource.getResource());
    • registerBeanDefinitions(doc, resource);
    • doRegisterBeanDefinitions(doc.getDocumentElement());
    • parseBeanDefinitions(root, this.delegate);
    • parseDefaultElement(ele, delegate);
    • processBeanDefinition(ele, delegate);
    • delegate.parseBeanDefinitionElement(ele);
    • registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition())
    • 扫描生成 BeanDefinition ClassPathBeanDefinitionScanner.doScan

    2.1 registerBeanDefinitions()

    public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
        // 委托模式,委托 BeanDefinitionDocumentReader 进行 document 解析
        BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
        int countBefore = getRegistry().getBeanDefinitionCount();
        // 具体解析过程
        documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
        return getRegistry().getBeanDefinitionCount() - countBefore;
    }
    

    2.2 parseBeanDefinitions()

    // DefaultBeanDefinitionDocumentReader#parseBeanDefinitions
    if (node instanceof Element) {
        Element ele = (Element) node;
        if (delegate.isDefaultNamespace(ele)) {
            // 3.1 默认标签解析
            parseDefaultElement(ele, delegate);
        } else { 
            // 3.2 自定义标签解析
            delegate.parseCustomElement(ele);
        }
    }
    

    3.1 默认标签解析

    • <bean id="" class="" />
    • DefaultBeanDefinitionDocumentReader#parseDefaultElement
    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
            importBeanDefinitionResource(ele);
        }
        else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
            processAliasRegistration(ele);
        }
        else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
            processBeanDefinition(ele, delegate);
        }
        else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
            doRegisterBeanDefinitions(ele);
        }
    }
    
    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
      // 4.1
      BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
      // 4.2 
      BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
    }
    
    // Bean 属性解析
    AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
    ele.hasAttribute(CLASS_ATTRIBUTE)
    ele.hasAttribute(PARENT_ATTRIBUTE)
    parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
    ele.hasAttribute(SINGLETON_ATTRIBUTE)
    ele.hasAttribute(SCOPE_ATTRIBUTE)
    ele.hasAttribute(INIT_METHOD_ATTRIBUTE)
    
    // BeanDefinitionReaderUtils.registerBeanDefinition()
    // DefaultListableBeanFactory 待定...
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    

    3.2 自定义标签解析

    • <context:component-scan base-package="com..." use-default-filters="true" />
    • 扫描包中的带有 @Component 的类
    • ContextNamespaceHandler#parse (父类 NamespaceHandlerSupport)
    • ComponentScanBeanDefinitionParser#parse
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        // base-package
        String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
        basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
        String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
        // 5.1 注解扫描器
        ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
        // 5.2 扫描并把类封装成 BeanDefinition 对象
        Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
        // 5.3
        registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
        return null;
    }
    

    5.1 configureScanner()

    protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {
        boolean useDefaultFilters = true;
        if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) {
            useDefaultFilters = Boolean.parseBoolean(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE));
        }
        ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters);
    }
    
    // 注解类型的过滤
    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
                Environment environment, @Nullable ResourceLoader resourceLoader) {
        if (useDefaultFilters) {
            registerDefaultFilters();
        }
    }
    
    private final List<TypeFilter> includeFilters = new ArrayList<>();
    this.includeFilters.add(new AnnotationTypeFilter(Component.class));
    

    5.2 doScan()

    1. 扫描基本包的路径,找 .class 文件
    2. 递归找 .class 文件
    3. 判断 .class 文件里是否有注解,includeFilter 里的@Component
    4. 变成 BeanDefinition 对象

    相关文章

      网友评论

          本文标题:Spring Bean 基础

          本文链接:https://www.haomeiwen.com/subject/weepvrtx.html