Spring源码篇二之什么是BeanDefinition和注册Bean的流程

tech2022-08-05  141

当你的才华还撑不起你的野心的时候,唯有静下心来学习。

spring运行流程图(https://www.processon.com/view/5f3fcab8e0b34d07118258cb?fromnew=1)

BeanDefintion对象是什么

       那么BeanDefinition对象具体是个什么呢?简单来说,在开发中是不管基于xml文件方式,还是基于注解类方式。把他们直接交给spring容器,spring容器是处理不了的,所以spring提供了一个BeanDefinition的对象来进行统一处理,不管是xml还是注解文件等,都给解析为对应的BeanDefinition的对象来进行处理,是不是非常妙。可以简单理解为下图,如果想看解析的直接对应关系可以看BeanDefinition接口的实现类都有哪些属性和定义的xml或注解属性都是一一对应的。一个bean对应一个BeanDefinition的实现类。

注册Bean的流程

       spring源码的AnnotationConfigApplicationContext的构造函数调用this()方法已经在上一篇讲解完成了。具体的详细点这里,查看上一篇。

public AnnotationConfigApplicationContext(Class... annotatedClasses) { this(); // 完成注解类的注册 register(annotatedClasses); // 第三篇讲 refresh(); }

       该执行到register(annotatedClasses);方法了,参数annotatedClasses就是传递过来的定义的注解类TestController.class

@Configuration @ComponentScan("com.online.manager") public class TestController { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestController.class); // TODO1 到这一步spring已经加载完成 UserController userController = context.getBean(UserController.class); } }

       register(annotatedClasses);方法就是把TestController.class转换为BeanDefinition对象注入到bean工厂中,通过以下调用链执行,最终完成功能的是doRegisterBean方法。        doRegisterBean方法,以下就是他的具体实现,他是把annotatedClass参数也就是我们对于的注解类TestController转换为BeanDefintion对象,然后注入到bean工厂中。

<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) { // 解析TestController注解类的属性,转换为对应的BeanDefinition对象,可以通过源码,看他具体实现 AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass); if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { return; } abd.setInstanceSupplier(instanceSupplier); // 解析他的BeanDefiniton,获取到作用域的元数据信息如 Singleton/prototype域 ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); // 填充数据,为BeanDefintion也就是对应的bean是哪一个作用域,默认是单例的 abd.setScope(scopeMetadata.getScopeName()); // 生成bean的id String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); // 填充数据,这个方法里处理了一些通用的注解,如@Lazy、@Primary比较简单,可以自己点进去查看 AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); // qualifiers 传过来就是null if (qualifiers != null) { for (Class<? extends Annotation> qualifier : qualifiers) { if (Primary.class == qualifier) { abd.setPrimary(true); } else if (Lazy.class == qualifier) { abd.setLazyInit(true); } else { abd.addQualifier(new AutowireCandidateQualifier(qualifier)); } } } // definitionCustomizers也是null for (BeanDefinitionCustomizer customizer : definitionCustomizers) { customizer.customize(abd); } // BeanDefinitionHolder其实就是对BeanDefintion包装,可以看出是个map结构beanName -> BeanDefintion, 看他的类定义就知道了 // 这么做的原因是为了少传递参数,把两个参数转换为了一个参数 就是这么简单 BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); // 代理 definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); // 向beanFactory的definitonMap的注册,直接put(beanName ,BeanDefintion)可自己点进去查看 BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); }

到这里register(annotatedClasses);方法就完成了向beanFactory容器里注册beanDefintion数据。Bean注册的流程就是,把一个注解类解析为对应的BeanDefintion对象,然后填充相应属性,然后加入到beanFactory的容器中,就完成了Bean的注册。注意,以上注册Bean只是向容器添加一些类元数据相关的信息,为后面创建对象打下基础,注意这时还没有实例化对象。 后面会将refresh方法,这个方法才是Spring的最重要的部分,也是在这个方法里面完成对象的创建的,不用弄混了。

最新回复(0)