spring第一篇 BeanDefinition(源码重点)

会有很多属性 具体就不一一介绍了 可以参考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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值