Spring源码分析系列(1)之bean工厂的创建+内置bean的注册(this()+this.register(componentClasses))

前置知识:

我们知道BeanFactory是用来生产bean的工厂,它是一个接口,他还有子接口ApplicationContext,提供更丰富的功能,来初始化Spring的上下文环境。

// 通过加载配置类,初始化spring的上下文环境(全注解开发)
AnnotationConfigApplicationContext context =
        new 
  AnnotationConfigApplicationContext(AppContextConfig.class);
// 从IOC容器获取bean
context.getBean("userServiceImpl", UserService.class);

AnnotationConfigApplicationContext(AppContextConfig.class)

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    // 先调用了自己的空参构造器,在自己的空参构造器中会调用父类GenericApplicationContext的空参构造器
    // 在父类的空参构造器中对beanFactory,进行了初始化
    this();
    // 注册该配置类
    this.register(componentClasses);
    // 刷新*************这才是主要方法**************
    this.refresh();
}

GenericApplicationContext(),父类空参构造器

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
    // bean工厂,也就是说bean工厂实际上是应用上下文的一个属性
    // 但应用上下文和bean工厂又同时实现了BeanFactory接口
    private final DefaultListableBeanFactory beanFactory;
    ......(省略了一些属性)
    public GenericApplicationContext() {
         this.customClassLoader = false;
         this.refreshed = new AtomicBoolean();
         // 创建bean工厂对象
        this.beanFactory = new      DefaultListableBeanFactory();
}
    ......
}   

AnnotationConfigApplicationContext()本类的空参构造器

// 可以看到AnnotationConfigApplicationContext它不仅是一个应用上下文,它的父类GenericApplicationContext还实现了BeanDefinitionRegistry接口,所以他也是一个BeanDefinition的注册器,什么是BeanDefinition?(往下看)
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
    // spring应用上下文中的读取器
    private final AnnotatedBeanDefinitionReader reader;
    // spring应用上下文中的扫描器
    private final ClassPathBeanDefinitionScanner scanner;
public AnnotationConfigApplicationContext() {
    StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
    // 初始化一个读取器,传入了上下文自己
    // 首先我们要知道,spring除了我们自己定义的bean之外,也有一些内置的bean,用来辅助我们自定义bean的生产(可以理解为工厂中的工具、原料)那么此方法中就是注册了spring的内置bean
    this.reader = new AnnotatedBeanDefinitionReader(this);
    createAnnotatedBeanDefReader.end();
    // 初始化一个扫描器,它仅仅是在我们外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象的,所以不做分析
    this.scanner = new 
        ClassPathBeanDefinitionScanner(this);
}
    .......
}

BeanDefinition是什么?

它是一个描述bean的类,就比如说:该bean对应的类的全类名是什么,该bean的beanName(就是xml文件中那个id),该bean是否单例......我们最终实例化对象,就是跟据这个BeanDefinition中的描述信息进行的。

我们可以看一下beanDefinition的内部结构:

AnnotatedBeanDefinitionReader(this),这里的this就是我们new的annotationConfigApplicationContext对象

public class AnnotatedBeanDefinitionReader {
    // 读取器也有一个属性是BeanDefinition的注册器
    private final BeanDefinitionRegistry registry;
    ......(省略了一些属性)
    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        this.beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;
        this.scopeMetadataResolver = new AnnotationScopeMetadataResolver();
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        Assert.notNull(environment, "Environment must not be null");
        // 设置当前上下文对象作为读取器的注册器
        this.registry = registry;
        this.conditionEvaluator = new ConditionEvaluator(registry, environment, (ResourceLoader)null);
        // 注册各种处理器,registerAnnotationConfigProcessors方法中又调用了registerAnnotationConfigProcessors方法,这个方法中就是各种处理器的注册了,我们以一个为例来看
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }
    .......
}

registerAnnotationConfigProcessors(registry, (Object)null)

    public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {
        .......
 RootBeanDefinition def;   
  if(!registry.containsBeanDefinition("org.springframework.context.annotation.internalConfigurationAnnotationProcessor")) {
      // 判断ConfigurationAnnotationProcessor处理器对应的beanDefinition是不是已经存在了,如果不存在就new一个(RootBeanDefinition是BeanDefinition的子类),并将beanClass设置为ConfigurationClassPostProcessor.class,实际上就是new一个对ConfigurationClassPostProcessor内置bean的描述对象。
        def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
       def.setSource(source);
      // 开始注册bean
       beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"));
        }
        ......
    }

registerPostProcessor()

private static BeanDefinitionHolder registerPostProcessor(BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
    // 给bean definition设置了一个角色,表明是内置bean
    /**
    int ROLE_APPLICATION = 0;    应用程序主要部分角色
    int ROLE_SUPPORT = 1;        这个 Bean 来自于用户配置。
    int ROLE_INFRASTRUCTURE = 2; 基础设施,表明是spring内置的bean
    **/
    definition.setRole(2);
    // 此处开始真正的注册bean,但是这是一个BeanDefinition的抽象方法,需要调用它的实现类中的方法,他有三个实现了此方法的类,我们刚刚在调用register的父类空构造器时,造了一个DefaultListableBeanFactory对象,所以自然是调用该bean工厂的注册方法了。
    registry.registerBeanDefinition(beanName, definition);
    return new BeanDefinitionHolder(definition, beanName);
}

我们刚刚一直在谈到注册bean实际上就是将内置bean对应的beanDefinition保存到bean工厂中。那为什么要保存beanDefinition呢?因为Spring是跟据beanDefinition中对bean的描述,来实例化对象的,就算自己定义的bean也是要被解析成一个beanDefinition并注册的。

registerBeanDefinition(beanName, definition)

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    ......
        // 用来保存BeanName对应的BeanDefinition对象
        private final Map<String, BeanDefinition> beanDefinitionMap;
        // 保存beanName
        private volatile List<String> beanDefinitionNames;
    ......
        public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
            ......
                // 提取两行核心代码
                // 把beanName作为key,beanDefinition作为value放入Map中
                 this.beanDefinitionMap.put(beanName, beanDefinition);
                // 把beanName放到list中
                this.beanDefinitionNames.add(beanName);
            ......
        }

我们来看一下现在的beanDefinitionMapbeanDefinitionNames的内部结构:

一个内置bean已经注册完成,它会接连注册好几个内置bean,都是用同样的方法,注册完成后,AnnotatedBeanDefinitionReader(this)方法,我们就分析完成了。

回到register(componentClasses)方法

// 可以看出,这里传入的是配置类数组
public void register(Class<?>... componentClasses) {
    Assert.notEmpty(componentClasses, "At least one component class must be specified");
    StartupStep registerComponentClass = this.getApplicationStartup().start("spring.context.component-classes.register").tag("classes", () -> {
        return Arrays.toString(componentClasses);
    });
    // 主要方法:又调用了读取器的注册方法,去注册配置类;此方法中会循环遍历数组,调用读取器的registerBean方法注册每个配置bean,registerBean方法中又调用了doRegisterBean方法
    this.reader.register(componentClasses);
    registerComponentClass.end();
}

registerBean(Class<?> beanClass)

public void registerBean(Class<?> beanClass) {
    // 可以看到,注册bean时,除了beanClass,其他都是null
    this.doRegisterBean(beanClass, (String)null, (Class[])null, (Supplier)null, (BeanDefinitionCustomizer[])null);
}

doRegisterBean()

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) {
    // 生成配置bean的BeanDefinition,前面已经说过了BeanDefinition就是用来描述bean的(抽象的说就是bean定义),从下面的构造器中可以看出,不仅设置了BeanClass为当前配置类,还获取了该类上注解元信息,通过metadata对象,就可以获取到类上的注解信息了
    /**
        public AnnotatedGenericBeanDefinition(Class<?> beanClass) {
            this.setBeanClass(beanClass);
            this.metadata = AnnotationMetadata.introspect(beanClass);
        }
    **/
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
    //判断是否需要跳过注解,spring中有一个@Condition注解,当不满足条件,这个bean就不会被解析注册
    // 这里提到了bean的解析,我们知道,刚刚生成的beanDefinition我们仅仅设置了beanClass为当前配置类,还没有解析bean,给beanDefinition的其他描述bean的属性设置值(比如是否单例.....),接下来就是做这件事
    if (!this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        abd.setInstanceSupplier(supplier);
        //解析bean的作用域,如果没有设置的话,默认为单例
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        abd.setScope(scopeMetadata.getScopeName());
        // 设置beanName,判断如果用户自己设置了name就用自定义的,没有设置就将类名首字母小写,作为beanName,默认传入的是null
        String beanName = name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry);
        //解析通用注解,填充到AnnotatedGenericBeanDefinition,解析的注解为Lazy,Primary,DependsOn,Role,Description,从刚刚设置的metadata中去获取
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
        int var10;
        int var11;
        // 注解处理(限定符处理),qualifiers是一个注解数组,如果我们以常规方式        AnnotationConfigApplicationContext context =
       //         new AnnotationConfigApplicationContext(AppContextConfig.class);去初始化spring,qualifiers就是null,如果以spring提供的其他特殊方式去注册,就可以传入了。
        if (qualifiers != null) {
            Class[] var9 = qualifiers;
            var10 = qualifiers.length;
​
            for(var11 = 0; var11 < var10; ++var11) {
                Class<? extends Annotation> qualifier = var9[var11];
                // 解析注解数组中的注解,重新设置beanDefinition的相应属性
                if (Primary.class == qualifier) {
                    abd.setPrimary(true);
                } else if (Lazy.class == qualifier) {
                    abd.setLazyInit(true);
                } else {
                    abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                }
            }
        }
​
        if (customizers != null) {
            BeanDefinitionCustomizer[] var13 = customizers;
            var10 = customizers.length;
​
            for(var11 = 0; var11 < var10; ++var11) {
                BeanDefinitionCustomizer customizer = var13[var11];
                customizer.customize(abd);
            }
        }
    // 把AnnotatedGenericBeanDefinition数据结构和beanName封装到一个对象中
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
        // 将配置类的beanDefinition注册到bean工厂中,与前面内置bean的注册相同,就是将beanName与baenDefinition封装到Map中,将beanName放到list中。Map与list都是bean工厂DefaultListableBeanFactory所维护的属性。
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }
}

至此,我们的配置类就注册完成了,我们看一下现在的beanDefinitionMapbeanDefinitionNames的内部结构:(自己想看,可以打断点,加上断点条件为beanName.equals("自己配置类名首字母小写"))

总结:上述 this()和this.register(componentClasses)方法中就是将内置bean和我们传的配置bean的beanDefinition进行了注册,还没处理标记了@Component等注解的自定义bean。

下一篇,refresh()......

如有问题欢迎指正讨论

参考博文:剑指Spring源码(二) - CodeBear - 博客园

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值