spring boot 註解@Component

yu15050186065發表於2020-10-14

@Component。
Spring提供進一步典型的註解:@Component,@Service,和 @Controller。@Component是任何Spring託管元件的通用註解。 而@Repository,@Service和@Controller是@Component針對更特定用例的專業化(分別在永續性,服務和表示層)。因此可以用他們來註解你的元件類與@Component具有同樣作用,通過與註解它們@Repository,@Service或者@Controller ,你能更好的區分資料,業務,控制層
這些註解也是aspect的理想切入點,例如,這些構造型註釋成為切入點的理想目標。@Repository,@Service和,並且@Controller在Spring框架的將來版本中還可以包含其他語義。因此,如果您選擇使用@Component或@Service對於您的服務層,@Service顯然是更好的選擇。同樣,如前所述,@Repository在持久層中已經支援將其作為自動異常轉換的標記。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
    String value() default "";
}

SpringApplication, 掉用this.refreshContext(context)時候會將掉用bean 定義,根據這些RootBeanDefinition將bean例項注入到IOC中

SpringApplication:
public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
        this.configureHeadlessProperty();
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.starting();

        Collection exceptionReporters;
        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            Banner printedBanner = this.printBanner(environment);
            context = this.createApplicationContext();
            exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
            this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            this.refreshContext(context);
            this.afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }

            listeners.started(context);
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
            this.handleRunFailure(context, var10, exceptionReporters, listeners);
            throw new IllegalStateException(var10);
        }

        try {
            listeners.running(context);
            return context;
        } catch (Throwable var9) {
            this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var9);
        }
    }

SpringApplication掉用ClassPathBeanDefinitionScanner通過basePackage掃描bean,生成bean 定義。

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Assert.notEmpty(basePackages, "At least one base package must be specified");
        Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet();
        String[] var3 = basePackages;
        int var4 = basePackages.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            String basePackage = var3[var5];
            Set<BeanDefinition> candidates = this.findCandidateComponents(basePackage);
            Iterator var8 = candidates.iterator();

            while(var8.hasNext()) {
                BeanDefinition candidate = (BeanDefinition)var8.next();
                ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
                candidate.setScope(scopeMetadata.getScopeName());
                String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
                if (candidate instanceof AbstractBeanDefinition) {
                    this.postProcessBeanDefinition((AbstractBeanDefinition)candidate, beanName);
                }

                if (candidate instanceof AnnotatedBeanDefinition) {
                    AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition)candidate);
                }

                if (this.checkCandidate(beanName, candidate)) {
                    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                    beanDefinitions.add(definitionHolder);
                    this.registerBeanDefinition(definitionHolder, this.registry);
                }
            }
        }
        return beanDefinitions;
 }
 private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
        LinkedHashSet candidates = new LinkedHashSet();

        try {
            String packageSearchPath = "classpath*:" + this.resolveBasePackage(basePackage) + '/' + this.resourcePattern;
            Resource[] resources = this.getResourcePatternResolver().getResources(packageSearchPath);
            boolean traceEnabled = this.logger.isTraceEnabled();
            boolean debugEnabled = this.logger.isDebugEnabled();
            Resource[] var7 = resources;
            int var8 = resources.length;

            for(int var9 = 0; var9 < var8; ++var9) {
                Resource resource = var7[var9];
                if (traceEnabled) {
                    this.logger.trace("Scanning " + resource);
                }

                if (resource.isReadable()) {
                    try {
                        MetadataReader metadataReader = this.getMetadataReaderFactory().getMetadataReader(resource);
                        if (this.isCandidateComponent(metadataReader)) {
                            ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                            sbd.setSource(resource);
                            if (this.isCandidateComponent((AnnotatedBeanDefinition)sbd)) {
                                if (debugEnabled) {
                                    this.logger.debug("Identified candidate component class: " + resource);
                                }

                                candidates.add(sbd);
                            } else if (debugEnabled) {
                                this.logger.debug("Ignored because not a concrete top-level class: " + resource);
                            }
                        } else if (traceEnabled) {
                            this.logger.trace("Ignored because not matching any filter: " + resource);
                        }
                    } catch (Throwable var13) {
                        throw new BeanDefinitionStoreException("Failed to read candidate component class: " + resource, var13);
                    }
                } else if (traceEnabled) {
                    this.logger.trace("Ignored because not readable: " + resource);
                }
            }

            return candidates;
        } catch (IOException var14) {
            throw new BeanDefinitionStoreException("I/O failure during classpath scanning", var14);
        }
    }

ClassPathBeanDefinitionScanner將掃描到的bean通過ClassPathScanningCandidateComponentProvider.includeFilters進行篩選,找到帶@Compnent的bean

ClassPathScanningCandidateComponentProvider:
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
        Iterator var2 = this.excludeFilters.iterator();

        TypeFilter tf;
        do {
            if (!var2.hasNext()) {
                var2 = this.includeFilters.iterator();

                do {
                    if (!var2.hasNext()) {
                        return false;
                    }

                    tf = (TypeFilter)var2.next();
                } while(!tf.match(metadataReader, this.getMetadataReaderFactory()));

                return this.isConditionMatch(metadataReader);
            }

            tf = (TypeFilter)var2.next();
        } while(!tf.match(metadataReader, this.getMetadataReaderFactory()));

        return false;
    }

AnnotationTypeFilter 是ClassPathBeanDefinitionScanner的一個filter,用來篩選@Compnent bean.

protected boolean matchSelf(MetadataReader metadataReader) {
        AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
        return metadata.hasAnnotation(this.annotationType.getName()) || this.considerMetaAnnotations && metadata.hasMetaAnnotation(this.annotationType.getName());
    }
AnnotationMetadata:
public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata {
    default Set<String> getAnnotationTypes() {
        return (Set)this.getAnnotations().stream().filter(MergedAnnotation::isDirectlyPresent).map((annotation) -> {
            return annotation.getType().getName();
        }).collect(Collectors.toCollection(LinkedHashSet::new));
    }

    default Set<String> getMetaAnnotationTypes(String annotationName) {
        MergedAnnotation<?> annotation = this.getAnnotations().get(annotationName, MergedAnnotation::isDirectlyPresent);
        return !annotation.isPresent() ? Collections.emptySet() : (Set)MergedAnnotations.from(annotation.getType(), SearchStrategy.INHERITED_ANNOTATIONS).stream().map((mergedAnnotation) -> {
            return mergedAnnotation.getType().getName();
        }).collect(Collectors.toCollection(LinkedHashSet::new));
    }

    default boolean hasAnnotation(String annotationName) {
        return this.getAnnotations().isDirectlyPresent(annotationName);
    }

    default boolean hasMetaAnnotation(String metaAnnotationName) {
        return this.getAnnotations().get(metaAnnotationName, MergedAnnotation::isMetaPresent).isPresent();
    }

    default boolean hasAnnotatedMethods(String annotationName) {
        return !this.getAnnotatedMethods(annotationName).isEmpty();
    }

    Set<MethodMetadata> getAnnotatedMethods(String var1);

    static AnnotationMetadata introspect(Class<?> type) {
        return StandardAnnotationMetadata.from(type);
    }
}

ApplicationContext使用DefaultListableBeanFactory通過RootBeanDefinition將bean注入到IOC中。

相關文章