第一步先介绍基于正常的扫描包的流(ConfigurationClassParser是如何扫描包)
1.invokeBeanFactoryPostProcessors
2.扫描一个包下的所有的class
3.是否设置了过滤器(这是一个大坑)
match逻辑
4.判断是否符合候选组件条件
针对上述过程分析
思路
代码演示
第一步先介绍基于正常的扫描包的流(ConfigurationClassParser是如何扫描包)
1.invokeBeanFactoryPostProcessors
2.扫描一个包下的所有的class
3.是否设置了过滤器
4.判断是否符合候选组件条件
针对上述过程分析
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
//是否标注@Component注解;如果是接口的话不会走这个逻辑
if (matchSelf(metadataReader)) {
return true;
}
ClassMetadata metadata = metadataReader.getClassMetadata();
if (matchClassName(metadata.getClassName())) {
return true;
}
//是否考虑接口;不管是默认的excludeFilters还是includeFilters
//里面的considerInherited和considerInterfaces都是false,都不会走这个逻辑
if (this.considerInterfaces) {
for (String ifc : metadata.getInterfaceNames()) {
// Optimization to avoid creating ClassReader for super class
Boolean interfaceMatch = matchInterface(ifc);
if (interfaceMatch != null) {
if (interfaceMatch.booleanValue()) {
return true;
}
}
else {
// Need to read interface to determine a match...
try {
if (match(ifc, metadataReaderFactory)) {
return true;
}
}
catch (IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not read interface [" + ifc + "] for type-filtered class [" +
metadata.getClassName() + "]");
}
}
}
}
}
return false;
}
主要解决一下问题
BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistryConfigurationClassPostProcessor#processConfigBeanDefinitions ClassPathBeanDefinitionScanner#doScan
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException { for (TypeFilter tf : this.excludeFilters) { if (tf.match(metadataReader, getMetadataReaderFactory())) { return false; } } //自定义扫描器,会在这里循环遍历所有的扫描器 for (TypeFilter tf : this.includeFilters) { if (tf.match(metadataReader, getMetadataReaderFactory())) { return isConditionMatch(metadataReader); } } return false; }
扫描的过程中
isCandidateComponent(metadataReader)
只牵涉到springIOC的过程,动态代理那一块会省略部分步骤
package com.nieyp;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
private String packages;
public CustomBeanDefinitionRegistryPostProcessor(String packages) {
this.packages = packages;
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
new CustomClassPathBeanDefinitionScanner(registry).doScan(packages);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
package com.nieyp;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.type.ClassMetadata;
import java.util.Set;
public class CustomClassPathBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {
public CustomClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
super(registry);
}
/**
* 如果组件是接口的话返回true
*
* AnnotationMetadata metadata = beanDefinition.getMetadata();
* return (metadata.isIndependent() && (metadata.isConcrete() ||
* (metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName()))));
*
* metadata里面的isxxxx能够判断当前的bean定义的所属类型
* @param beanDefinition
* @return
*/
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
return beanDefinition.getMetadata().isInterface();
}
@Override
protected Set doScan(String... basePackages) {
addIncludeFilter((metadataReader, metadataReaderFactory) -> {
ClassMetadata metadata = metadataReader.getClassMetadata();
if (metadata.isInterface()) {
return true;
}
return false;
});
Set beanDefinitionHolders = super.doScan(basePackages);
查看第一步的结果beanDefinitionHolders里面的bean定义:已经扫描到了某一个包下的接口
下面会重构bean定义:偷天换日(生成代理对象)
@Override
protected Set doScan(String... basePackages) {
//增加包含过滤器,元数据为接口的话,返回true
addIncludeFilter((metadataReader, metadataReaderFactory) -> {
ClassMetadata metadata = metadataReader.getClassMetadata();
if (metadata.isInterface()) {
return true;
}
return false;
});
Set beanDefinitionHolders = super.doScan(basePackages);
for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
/** 不能转为RootBeanDefinition
* RootBeanDefinition beanDefinition = (RootBeanDefinition) beanDefinitionHolder.getBeanDefinition();
* class org.springframework.context.annotation.ScannedGenericBeanDefinition cannot be cast to class org.springframework.beans.factory.support.RootBeanDefinition
*/
ScannedGenericBeanDefinition beanDefinition = (ScannedGenericBeanDefinition) beanDefinitionHolder.getBeanDefinition();
String beanClassName = beanDefinition.getBeanClassName();
//重构bean定义
/**
* 如果采用definition.getPropertyValues()方式的话,
* 类似definition.getPropertyValues().add("interfaceType", beanClazz);
* 则要求在FactoryBean(本应用中即CustomFactoryBean)提供setter方法,否则会注入失败
* 如果采用definition.getConstructorArgumentValues(),
* 则FactoryBean中需要提供包含该属性的构造方法,否则会注入失败
*/
//这一部分可以参考mybatis源码 设置ConstructorArgumentValues()会通过构造器初始化对象
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName);
//这一步不再介绍牵涉到aop的知识,后续会给出详细代码
beanDefinition.setBeanClass(CustomFactoryBean.class);
//设置通过类型自动装配,这里采用的是byType方式注入,类似的还有byName等
beanDefinition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
}
return beanDefinitionHolders;
}