概述
@Component派生性
- spring可以扫描到,标注了@Component,以及使用了@Component注解的注解,可以是自定义注解。这种spring扫描到的注解,以及类似派生出的注解称为@Component的派生性。
原理
1 寻找处理器
- 在spring的xml文件中,根据Spring可扩展的XML编写扩展机制。元素XML Schema命名空间需要与其处理器建立映射关系,且配置在相对于classpath的规约资源/META-INF/spring.handlers中。
- 查找的Context处理器: 使用标签 < context:component-scan > 进行开启注解扫描,查询context的处理器为
- 当扫描到< context:component-scan >注解时,调用ContextNamespaceHandler的init方法,注册了一些解析器,component-scan的解析器为ComponentScanBeanDefinitionParser
public void init() {
registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
}
- 既然能解析出@Component注解,以及“派生”注解,关键在于该类中。
2 注解解析
- 在解析标签时,调用BeanDefination解析器中的parse方法
public class ComponentScanBeanDefinitionParser implements BeanDefinitionParser {
private static final String BASE_PACKAGE_ATTRIBUTE = "base-package";
String CONFIG_LOCATION_DELIMITERS = ",; tn";
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
//解析元素的base-package属性,获取扫描的根路径
String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
//获取基本路径
String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
// Actually scan for bean definitions and register them.
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
//在根路径下,扫描所有的注解,返回BeanDefinitionHolder信息
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
return null;
}
}
- ClassPathBeanDefinitionScanner.doScan
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) {
//(真正获取beanDefinition的地方)获取bean的定义信息,来源在此,后续进行封装,转换
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)) {
//根据定义信息,创建definitionHodler对象
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//bean定义增加,definitionHolder
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
- ClassPathBeanDefinitionScanner.findCandidateComponents
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
}
else {
//执行此处,该方法时父类的方法
return scanCandidateComponents(basePackage);
}
}
- ClassPathScanningCandidateComponentProvider.scanCandidateComponents
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
//真正的扫描到的bean定义信息
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
//String CLASSPATH_ALL_URL_PREFIX = "classpath*:";
//此处将.换成/,最后的结果为 classpath*:com/learning/**/*.class
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
//得到类资源集合,扫描到所有的类路径,如图1
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
for (Resource resource : resources) {
if (traceEnabled) {
logger.trace("Scanning " + resource);
}
//1. 如果资源可读,即可获取
if (resource.isReadable()) {
try {
//2. 获取到元信息读取器,其中包括,类信息和注解信息,如图二
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
//3. 执行判断是否符合 过滤器规则,函数内部用过滤器 对metadataReader 过滤
if (isCandidateComponent(metadataReader)) {
//4. 把符合条件的 类转换成 BeanDefinition
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
//5. 再次判断 如果是实体类 返回true,如果是抽象类,但是抽象方法 被 @Lookup 注解注释返回true
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
}
//6. 将自定义注解的,Bean定义信息,加到bean定义信息集合中
candidates.add(sbd);
}
...
}
}
...
}
...
}
}
...
return candidates;
}
//判断是否是合理的元素,通过排除过滤器,和包含过滤器进行验证
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
//属于排除的类型
for (TypeFilter tf : this.excludeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return false;
}
}
//属于包含的类型
for (TypeFilter tf : this.includeFilters) {
//此方法会判断,tf是否与元信息匹配,比如,Component会匹配,Service,Controller,以及自定义注解
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return isConditionMatch(metadataReader);
}
}
return false;
}
- 在父类初始化的时候,初始化了includeFilters的类型
public ClassPathScanningCandidateComponentProvider(boolean useDefaultFilters, Environment environment) {
if (useDefaultFilters) {
registerDefaultFilters();
}
setEnvironment(environment);
setResourceLoader(null);
}
//-------------registerDefaultFilters
protected void registerDefaultFilters() {
//注解了Component类型
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
...
}
- 图1
- 图二
自定义过滤规则–不依赖spring标签
- 通过源码可以知晓,过滤的规则主要在include和exclude过滤器类,主要在于ClassPathBeanDefinitionScanner的scan方法,进行扫描包,获取标注的类。思路:通过后置处理器,将自定义的过滤规则加入,扫描自定义的包,即可
- 代码
- 后置处理器
@Component public class CustomBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { //1.定义扫描的执行类 ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry); //2.注册过滤的类型 TypeFilter includeFilter = new AnnotationTypeFilter(CustomComponent.class); //3.增加包含的过滤类型 scanner.addIncludeFilter(includeFilter); //4.添加扫描包 String[] basePackages = {"com.book.firstspringboot.dto"}; //5.扫描包中的类型,会自动注入到spring容器中 scanner.scan(basePackages); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } }
- 自定义标签
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface CustomComponent { }
- controller类
@RestController @RequestMapping("/test") public class FirstController { @Autowired private CustomDto dto; @RequestMapping("/t") public String print(){ return dto.custom(); } }
scan方法
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);
}
最后
以上就是辛勤路人为你收集整理的SpringBoot--003--理解@Component"派生性"原理的全部内容,希望文章能够帮你解决SpringBoot--003--理解@Component"派生性"原理所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复