• Spring源码分析之BeanDefinition


    前言

    我们定义的所有Bean,不管是通过XML文件定义的,或者通过@Component注解定义的,或者通过@Bean注解定义的,
    最后都会转换成一系列的BeanDefinition对象,保存到BeanDefinitionRegistry(注册表)中。
    BeanDefinition和Bean实例的关系就类似于Java类和Java对象的关系,Spring通过各种来源如XML或JavaConfig来加载BeanDefinition,
    后续通过BeanDefinition来创建Bean实例。BeanDefinition中保存了Bean的所有信息,如名称,所属Class,是否延迟加载等。

    BeanDefinition定义

    BeanDefinition接口定义如下

    public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    
       //默认只提供singleton(单例)和prototype(原型,每次都会创建对象)两种,但也可以扩展
       //如基于web的扩展的scope有request, session
       String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
       String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
    
       //用户定义的Bean一般使用这个
       int ROLE_APPLICATION = 0;
       //暂时不知道哪里使用
       int ROLE_SUPPORT = 1;
       //Spring内部定义的Bean一般使用这个
       int ROLE_INFRASTRUCTURE = 2;
    
       //所属父Bean,可以继承父Bean的配置信息
       void setParentName(String parentName);
       String getParentName();
    
       //Bean的类名称,后续要通过反射来创建Bean实例
       void setBeanClassName(String beanClassName);
       String getBeanClassName();
    
       //Bean的scope,一般我们自己定义的Bean默认就是singleton
       void setScope(String scope);
       String getScope();
    
       //设置是否懒加载,默认非懒加载(会在创建ApplicationContext的过程中提前创建Bean,懒加载的话就是在第一次getBean()时创建Bean)
       void setLazyInit(boolean lazyInit);
       boolean isLazyInit();
    
       //设置该Bean依赖的所有的Bean(这里的依赖不是指属性依赖@Autowire这种),而是约定一种依赖关系,如A依赖B,那么在创建A前必须先创建B
       void setDependsOn(String... dependsOn);
       String[] getDependsOn();
    
       //设置该Bean是否可以注入到其他Bean中,只对根据类型注入有效,如果根据名称注入,即使这边设置了false也是可以的,默认为true
       void setAutowireCandidate(boolean autowireCandidate);
       boolean isAutowireCandidate();
    
       //是否为主要,同一接口的多个实现,如果没有指定名字,Spring会优先选择设置primary为true的Bean
       void setPrimary(boolean primary);
       boolean isPrimary();
    
       // 如果该Bean使用工厂方法来创建,需要指定工厂Bean名称。
       void setFactoryBeanName(String factoryBeanName);
       String getFactoryBeanName();
    
       //指定工厂类中的工厂方法名称
       void setFactoryMethodName(String factoryMethodName);
       String getFactoryMethodName();
    
       //构造器参数
       ConstructorArgumentValues getConstructorArgumentValues();
    
       //Bean中的属性值
       MutablePropertyValues getPropertyValues();
    
       //是否为singleton
       boolean isSingleton();
    
       //是否为prototype
       boolean isPrototype();
    
       //如果这个Bean被设置为abstract,那么不能被实例化,
       boolean isAbstract();
    }
    

    相关类图如下

    Spring提供了不同类型的BeanDefinition实现,
    ScannedGenericBeanDefinition: 扫描@Component注解加载的BeanDefinition。
    ConfigurationClassBeanDefinition: 扫描@Configuration注解类下包含@Bean注解的方法加载的BeanDefinition。
    GenericBeanDefinition: 通用的BeanDefinition实现。

    BeanDefinitionRegistry

    相关类图如下

    DefaultListableBeanFactory就是IOC容器的最终实现类,既实现了BeanFactory接口,也实现了BeanDefinitionRegistry接口,
    所以它不仅是Bean容器,也是BeanDefinition注册表,同时管理Bean和BeanDefinition。

    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    import lombok.Setter;
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    
    public class TestBeanDefinition {
    
      public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder
            .genericBeanDefinition(UserService.class);
        definitionBuilder.addPropertyValue("username", "lisi");
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
          System.out.println(beanDefinitionName);
        }
        System.out.println("==========");
        beanFactory.registerBeanDefinition("userService", definitionBuilder.getBeanDefinition());
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
          System.out.println(beanDefinitionName);
        }
        UserService userService = (UserService) beanFactory.getBean("userService");
        System.out.println(userService.getUsername());//lisi
      }
    
      @Setter
      @Getter
      @NoArgsConstructor
      @AllArgsConstructor
      public static class UserService {
    
        private String username;
    
      }
    
    }
    

    我们可以自己创建一个BeanDefinition,将它注册到BeanDefinitionRegistry,后续BeanFactory就根据BeanDefinition来创建Bean实例。
    DefaultListableBeanFactory内部是通过一个ConcurrentHashMap来存储Bean名称和BeanDefinition的对应关系的。

    参考

    Spring IOC 容器源码分析
    RootBeanDefinition与GenericBeanDefinition (转)

  • 相关阅读:
    C++ std::map::erase用法及其陷阱
    写在分类之首-----to do list!
    Gradle系列教材(译)
    Android进阶-UIL分析
    ArrayList源码解析
    Android进阶-MVP
    高质量代码-树的子结构
    高质量代码-并和链表
    高质量代码-翻转链表
    高质量代码-链表中倒数第k个结点
  • 原文地址:https://www.cnblogs.com/strongmore/p/16221918.html
Copyright © 2020-2023  润新知