此处我们选择SpringBoot典型的资源加载方式Class方式来分析,在应用程序启动入口我们使用的是SpringApplication.run(Example.class, args);而Example.class是我们的main函数所在类,以它作为资源来加载。
// BeanDefinitionLoader.java private int load(Class<?> source) { // ① if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) { // Any GroovyLoaders added in beans{} DSL can contribute beans here GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class); load(loader); } // ② if (isComponent(source)) { this.annotatedReader.register(source); return 1; } return 0; }① - 判断是否支持Groovy
② - 判断是否包含@Component注解,如果包含才开始注册
① - 从缓存获取被加载的资源类是否有@Component注解的缓存
默认情况下是没有缓存,此时将会去查找Example.class是否包含@Component注解。那在默认情况下我们的启动类并未直接标明这个注解, 一个典型的SpringBoot Web应用如下:
@RestController @SpringBootApplication public class Example { @RequestMapping("http://www.likecs.com/") String home() { return "Hello World!"; } public static void main(String[] args) { SpringApplication.run(Example.class, args); } }实际上@RestController和@SpringBootApplication两个注解都包含了@Component注解。因此Example.class自然也就具有@Component注解,感兴趣的可以亲自点进去看看这两个注解内部。更多细节将来会单独分析。在确定了它支持@Component注解之后,开始加载Bean。
// BeanDefinitionLoader#load(Class<?> source) this.annotatedReader.register(source); // AnnotatedBeanDefinitionReader.java <T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) { // ① AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass); // ② if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { return; } // ③ abd.setInstanceSupplier(instanceSupplier); // ④ ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); abd.setScope(scopeMetadata.getScopeName()); String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); // ⑤ AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); // ⑥ 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)); } } } // ⑦ for (BeanDefinitionCustomizer customizer : definitionCustomizers) { customizer.customize(abd); } // ⑧ BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); }① - 创建一个带注解元数据的类定义。
② - 判断是否有@Conditional注解,以确定是否满足条件需要排除。
③ - 设置一个创建Bean的回调,基本都是空值。
④ - 获取当前Bean的作用域元数据,判断依据是是否包含@Scope注解。ScopeMetadata包含类的作用域描述(singleton | prototype)和代理模式描述ScopedProxyMode,默认为单例模式,不使用代理创建。
⑤ - 处理常用注解,包括@Lazy、@Primary、@Role、@Description、@DependsOn,他们将被设置到BeanDefinition的属性当中。
⑥ - 检查传入的Qualifiers。
⑦ - 暂时不知道干啥的,以后再说
⑧ - 确认好当前Bean的代理模式,并注册。