使用过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)