记一次Spring注解Component无法将类添加到spring容器

一次使用模板方法模式,刷刷刷两个类写好

@Component
public abstract class SceneRunAbstractHandler {

    /**
     * 获取当前类型的执行
     *
     * @return 类型标识如custom_run,env_run
     */
    public abstract String getType();



    public abstract void customRunConf(SceneRunQueryDto sceneRunQueryDto);

    /**
     * 执行
     */
    public void run(SceneRunQueryDto sceneRunQueryDto) {
    }

    /**
     * 后置处理
     * @param sceneRunQueryDto
     */
    public abstract void postProcess(SceneRunQueryDto sceneRunQueryDto);

@Component
public abstract class ConfSceneRunHandler extends SceneRunAbstractHandler {

    /**
     * 获取当前类型的执行
     *
     * @return 类型标识如custom_run, env_run
     */
    @Override
    public String getType() {
        return SceneRunTypeEnum.CONF_RUN.getCode();
    }

    /**
     * @param sceneRunQueryDto
     */
    @Override
    public void customRunConf(SceneRunQueryDto sceneRunQueryDto) {

    }

    /**
     * 后置处理
     *
     * @param sceneRunQueryDto
     */
    @Override
    public void postProcess(SceneRunQueryDto sceneRunQueryDto) {

    }

在使用类的时候怎么都无法从容器中获取,发现spring容器中连类的beanDefnition都没有,心想不至于啊,稍微搜索了一下,网上都是说什么类型重复了啥的,一搜索并没有,只能自己动手丰衣足食了
首先我们稍微理一下spring的bean生命周期,
当我们配置@ComponentScan后,spring就会按照正则匹配,从target目录下扫描class文件,然后读取class文件解析成MetadataReader,然后对MetadataReader进行分析,过滤,然后生成BeanDefinition。

public Set<BeanDefinition> findCandidateComponents(String basePackage) {
		Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();
		try {
			String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
					resolveBasePackage(basePackage) + '/' + this.resourcePattern;
			Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
			boolean traceEnabled = logger.isTraceEnabled();
			boolean debugEnabled = logger.isDebugEnabled();
			for (Resource resource : resources) {
				if (traceEnabled) {
					logger.trace("Scanning " + resource);
				}
				if (resource.isReadable()) {
					try {
						MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
					//这里处理ComponentScan的include和exclude
						if (isCandidateComponent(metadataReader)) {
							ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
							sbd.setResource(resource);
							sbd.setSource(resource);
				//这里可以看到解析成类的云数据后,我们要判断类是否有正确的注解
							if (isCandidateComponent(sbd)) {
								if (debugEnabled) {
									logger.debug("Identified candidate component class: " + resource);
								}
								candidates.add(sbd);
							}
							else {
								if (debugEnabled) {
									logger.debug("Ignored because not a concrete top-level class: " + resource);
								}
							}
						}
						else {
							if (traceEnabled) {
								logger.trace("Ignored because not matching any filter: " + resource);
							}
						}
					}
					catch (Throwable ex) {
						throw new BeanDefinitionStoreException(
								"Failed to read candidate component class: " + resource, ex);
					}
				}
				else {
					if (traceEnabled) {
						logger.trace("Ignored because not readable: " + resource);
					}
				}
			}
		}

我们再看看我们类被过滤的代码块

	protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
		AnnotationMetadata metadata = beanDefinition.getMetadata();
		//isConcrete这个方法主要校验当前类或者其子类是否是具体的类,非抽象,非接口
		return (metadata.isIndependent() && (metadata.isConcrete() ||
				(metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName()))));
	}

仔细看看我们的代码,我们的子类继承了抽象类,然后它自己也是abstract的,所以直接被过滤,终于就找到原因了。
总结:复制黏贴害人不浅

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值