前情提要
Spring Bean的 四种装配模式外,还有一种自动策略。
当只有一个 构造方法,并且构造方法里有参数。
会进行 aurowireConstructor(beanName, mdb, ctors, args)
- spring扫描不能直接new的方C法
@DependsOn
@Prototype 执行的时候new
所以需要先解析验证。
scan-parse(会变成BeaDefinition)-validate(info)-new(开始spring的生命周期)
可以这么理解:
beanDefinition之于Spring
相当于class之于java对象
- 常量(BeanDefinition)
- SCOPE_SINGLETON
ROLE_APPLICATION
setParentName
//自动装配候选对象 ,被装配
setAutowireCandidate
//候选对象最高级
setPrimary
BeanDefinition所有属性都能找到与之匹配的 xml配置。
ac.getBean(XXX);是从DefaultSingletonBeanRegistry.singletonObjects.get(XXX)
- abstractApplicationContext
abstractApplicationContext.refresh()
1 | //这里初始化对象。还未装配 |
- 扫描
- parse
- validate
- life 遍历map得到BeanDefinition实例化。
BeanDefinition
各方法说明:
setPrimary:
多个接口实现的时候,自动注入候选的时候排第一。
- 关键父类
AbstractBeanDefinition
ChildBeanDefinition,RootBeanDefinition Spring 2.5的时候用
GenericBeanDefinition
现在常用。
xml 配置里的
spring容器会进行扫描。扫描后会根据bendefinition里描述的进行实例化。
abstract = true 必须要有 beanClass
- RootBeanDefinition
减少不同 bean配置多种相同相同属性值的 工作量 abstract=true
parent = ‘xxx’
spring 2.5之前有这种写法。后面更方便了用扫描,用标签。
问题:RootBeanDefinition也有 setParentName(),为什么要多一个ChildBeanDefinition ?
RootBeanDefinition一般作为父出现,或者一般BD出现。但是不作为子BD出现。
为什么要这样规定?为什么设置Root的Parent要抛出异常?
合并BeanDefinition?
- AnnotatedBeanDefinitionReader
作用:解析@Configuration 这标签会去扫描
1 | public AnnotationConfigApplicationContext() { |
beanReader = AnnotatedBeanDefinitionReader(this);
把 配置的AppConfig 变成 BeanDefinition
其他的 要完成扫描的时候去new 其他BD.
1 | this.reader = new AnnotatedBeanDefinitionReader(this); 这么写是为了后面能通过 context.register.registBean(标签) 来扩展自定义标签。 |
注意这里是为了扩展,spring启动的时候并不是用这个scaner去扫描。
实际上用的是,在BeanDefinitionRegistry这个后置处理器。
ConfigutationClassPostProcessor.postProcessBanDefinitionRegistry(registry)
->
这里找到 registry里初始化的BeanDefinition,进行parse
ConfigurationClassParser.parse(Set
这个方法里会判断 参数是否实现了 AnnotatedBeanDefinition
bd instanceof AnnotatedBeanDefinition
ConfigurationClassParser.processConfigurationClass
//这段很有意思,扫描结束后会将sourceClass设置为null。说明所有的BeanDefinition都扫描出来了。
1 | do { |
1 | protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) |
doProcessConfigurationClass
这里是实现。
实际识别了@Component @ComponentScan @ImportSource 等标签。
然后在
ComponentScanAnnotationParser
类里的
public Set
进行实际的扫描,先new 出了
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
再判断各种includerFilter excluderFilter
最后根据 标签配置的 包路径进行文件扫描。
从而扫描出Beandefinition 放到BeanDeinitionMap
小总结:
Beandefinition决定了spring 中Bean的各种特征。
class-beandefinition-springbean。
通过beandefinition spring定义了一套 spring bean的属性特征。
GenericBeanDefinition追加了setBeanClass