会有很多属性 具体就不一一介绍了 可以参考spring官网
下面是类图 早期的spring主要是RootBeanDefinition和ChildBeanDefinition 一个是父 一个是子
后面增加了一个GenericBeanDefinition代替2者 但涉及merge的操作还是要用RootBeanDefinition
1 两个类介绍
1.1 AnnotatedBeanDefinitionReader 初始化容器会先初始化这个类
public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) {
registerBean(componentClass);
}
}
这个类有一个register方法 就是注册一个beandefinition
还有个很重要的功能 就是把spring一些内置的处理器变成bd 包括Bean工厂和Bean的
ConfigurationClassPostProcessor
AutowiredAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor
EventListenerMethodProcessor
DefaultEventListenerFactory
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
后续在这里被实例化 refresh方法里的
invokeBeanFactoryPostProcessors方法
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
1.2 ClassPathBeanDefinitionScanner
这个是扫描路径的类 会将符合条件的类变成beandefinition并注册
public int scan(String... basePackages) {
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
doScan(basePackages);
// Register annotation config processors, if necessary.
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}
/**
* Perform a scan within the specified base packages,
* returning the registered bean definitions.
* <p>This method does <i>not</i> register an annotation config processor
* but rather leaves this up to the caller.
* @param basePackages the packages to check for annotated classes
* @return set of beans registered if any for tooling registration purposes (never {@code null})
*/
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
doscan里面会有个收集过程
findCandidateComponents
会有这么一段代码 判断是否需要收集
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
if (isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
}
candidates.add(sbd);
}
这里我们可以开启扩展 类似mybatis
public class TydScaner extends ClassPathBeanDefinitionScanner {
@Override
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
return true;
}
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
return true;
}
public TydScaner(BeanDefinitionRegistry registry) {
super(registry);
}
// @Override
// public void addIncludeFilter(TypeFilter includeFilter) {
// super.addIncludeFilter(includeFilter);
// }
}
这样的扫描 直接2层判断都返回TRUE 这样包里的类都会被扫描到
也可以写一个扫描注解的过滤器 然后不重写MetadateReader为入参的isCandidateComponent方法,或者重写第二个方法 入参是bd的 在里面根据bd的属性重写 例如是否是接口
AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(MyScan.class);
tydScaner.addIncludeFilter(annotationTypeFilter);
int scan = tydScaner.scan("com.tyd.study.spring.bean.scan.bean");
System.out.println(scan);
//注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface MyScan {
}
打上注解
@MyScan
public class MyScanBean {
}
2 BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor
BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor
在spring的
invokeBeanFactoryPostProcessors方法里
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
会查找
BeanDefinitionRegistryPostProcessor类型的beandifinition,
AnnotatedBeanDefinitionReader在初始化的时候会加载一个叫 ConfigurationClassPostProcessor的类变成了BD,在invokeBeanFactoryPostProcessor的getbean()方法的时候实例化
所以spring的玩法都是需要先创建BD 内置的就提前实例化,通过内置的处理器(ConfigurationClassPostProcessor)再去扫描包下的Bd 包括程序员自定义的BeanDefinitionRegistryPostProcessor,再来执行自定义的扫描 ,直到扫描出所有的BD
扫描的方法
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
这个postProcessBeanDefinitionRegistry会在parse的时候 会将程序员自己扩展的
实现了 BeanDefinitionRegistryPostProcessor类的变成bd 然后继续扫描,程序员自己定义的一般没有实现
PriorityOrdered和Ordered 这2个接口是定义顺序的 会先循环实现了这2个接口的 最后才到程序员自己实现的 然后通过一个while循环 为啥有循环是因为可能这个BeanDefinitionRegistryPostProcessor扫描完后 又会多出新的BeanDefinitionRegistryPostProcessor类型的bd 需要一直扫描,beanFactory的扫描也是如此 只不过没有循环 这里比较费解?
在BeanDefinitionRegistryPostProcessor的扫描过程中
processImports会扫描出Import上面的类
// Process any @ComponentScan annotations
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
以Mybatis举例子
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({MapperScannerRegistrar.class})
@Repeatable(MapperScans.class)
public @interface MapperScan
类要实现 ImportBeanDefinitionRegistrar 接口
public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware
上面是老版的做法 现在是新版的做法
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {
private String basePackage;
private boolean addToConfig = true;
private SqlSessionFactory sqlSessionFactory;
private SqlSessionTemplate sqlSessionTemplate;
private String sqlSessionFactoryBeanName;
private String sqlSessionTemplateBeanName;
private Class<? extends Annotation> annotationClass;
private Class<?> markerInterface;
private ApplicationContext applicationContext;
private String beanName;
private boolean processPropertyPlaceHolders;
private BeanNameGenerator nameGenerator;
public MapperScannerConfigurer() {
}
定义了一个BeanDefinitionRegistryPostProcessor
老版的是通过ConfigurationClassPostProcessor扫描到import注解再执行ImportBeanDefinitionRegistrar扫描出来的Mapper变成了bd
新版是ConfigurationClassPostProcessor 扫描完后将MapperScannerConfigurer变成了一个BD,然后再执行这个的postProcessBeanDefinitionRegistry方法将MAPPER变成了BD