上一章总结到,AnnotationConfigApplicationContext提供两种方式注册bean,一是注册指定的bean,二是扫描指定的包。本章主要描述前者的过程。
注册指定的bean
AnnotatedBeanDefinitionReader.register()向容器注册指定bean。该方法完成整个过程的调用,其总结步骤如下
- 解析元数据信息,如作用域
- 对bean定义的通用注解处理
- 对qualifiers数据处理
- 根据作用域创建代理对象
- 注册BeanDefinition
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| public void register(Class<?>... annotatedClasses) { for (Class<?> annotatedClass : annotatedClasses) { registerBean(annotatedClass); } } public void registerBean(Class<?> annotatedClass) { doRegisterBean(annotatedClass, null, null, null); }
<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); }
|
解析元数据信息
该过程由AnnotationScopeMetadataResolver.resolveScopeMetadata()实现,主要用于解析bean是原生类型(prototype)还是单例类型(singleton)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) { ScopeMetadata metadata = new ScopeMetadata(); if (definition instanceof AnnotatedBeanDefinition) { AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition; AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor( annDef.getMetadata(), this.scopeAnnotationType); if (attributes != null) { metadata.setScopeName(attributes.getString("value")); ScopedProxyMode proxyMode = attributes.getEnum("proxyMode"); if (proxyMode == ScopedProxyMode.DEFAULT) { proxyMode = this.defaultProxyMode; } metadata.setScopedProxyMode(proxyMode); } } return metadata; }
|
处理通用注解
这里为啥叫通用注解,我其实觉得不太合适,我就是英文直译过来的。因为在我看来通用注解不应该只包含@Lazy、@Primary、@DependsOn。或者从某个角度来说,所有注解都应该通用。不过好像除了通用能简单描述一下,好像也没有其他更合适的词了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) { processCommonDefinitionAnnotations(abd, abd.getMetadata()); }
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) { AnnotationAttributes lazy = attributesFor(metadata, Lazy.class); if (lazy != null) { abd.setLazyInit(lazy.getBoolean("value")); } else if (abd.getMetadata() != metadata) { lazy = attributesFor(abd.getMetadata(), Lazy.class); if (lazy != null) { abd.setLazyInit(lazy.getBoolean("value")); } }
if (metadata.isAnnotated(Primary.class.getName())) { abd.setPrimary(true); } AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class); if (dependsOn != null) { abd.setDependsOn(dependsOn.getStringArray("value")); }
if (abd instanceof AbstractBeanDefinition) { AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd; AnnotationAttributes role = attributesFor(metadata, Role.class); if (role != null) { absBd.setRole(role.getNumber("value").intValue()); } AnnotationAttributes description = attributesFor(metadata, Description.class); if (description != null) { absBd.setDescription(description.getString("value")); } } }
|
根据作用域创建代理对象
这个方法存在的意义是为了区分使用jdk代理还是cglib代理,这里主要为引入AOP埋下伏笔,主要还是在AOP中使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| static BeanDefinitionHolder applyScopedProxyMode( ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode(); if (scopedProxyMode.equals(ScopedProxyMode.NO)) { return definition; } boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS); return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass); }
|
注册BeanDefinition
向IOC中注册BeanDefinition跟XML一样,都调用的是BeanDefinitionReaderUtils.registerBeanDefinition()。spring源码之IOC - xml - 注册BeanDefinition
总结
整体来说,注解配置bean比XML要简单,在spring内部实现也要简单。没有复杂的xml解析过程,对应的Class属性值、id、name,都能直接获取的到,然后将其保存在BeanDefinition中,并注册IOC就完成了容器启动。