为什么abstract @service注解的类不被加载到beanfactory中

2022-03-29 14:38:32 浏览数 (3)

使用过spring开发的开发者对@Service注解以及@Autowired注解不会陌生,系统在启动时会把@Service注解的类加载到BeanFactory中,然后就可以通过@Autowired注解的方式注入Service类实例,但并不是所以被@Service注解的类都会被加载到系统中,那么到底哪些类会被加载到系统中(也就是满足什么条件才会被加载呢),这个看下ClassPathScanningCandidateComponentProvider类的findCandidateComponents方法:

代码语言:javascript复制
	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);
						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);
					}
				}
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
		}
		return candidates;
	}

下面再看下下面这个方法:

代码语言:javascript复制
	protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
		AnnotationMetadata metadata = beanDefinition.getMetadata();
		return (metadata.isIndependent() && (metadata.isConcrete() ||
				(metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName()))));
	}

上面这段代码的意思就是:

1.类是独立的(独立类或者是嵌套内部类)

2.类是具体的(不是接口也不是抽象类)

3.类是抽象的且这个类都被Lookup注解的方法

也就是@Service被加载到系统需要满足条件1 && (条件2 || 条件3)

0 人点赞