Spring源码之@Configuration

@Configuration注解提供了全新的bean创立形式。最后spring通过xml配置文件初始化bean并实现依赖注入工作。从spring3.0开始,在spring framework模块中提供了这个注解,搭配@Bean等注解,能够齐全不依赖xml配置,在运行时实现bean的创立和初始化工作。例如:

public interface IBean {}public class AppBean implements IBean{}// @Configuration申明了AppConfig是一个配置类@Configuration // 显式扫描需应用组件@ComponentScan("xxx.xxx")public class AppConfig {    // @Bean注解申明了一个bean,bean名称默认为办法名appBean    // 默认状况下bean的名称和办法名称雷同    @Bean     IBean appBean(){        return new AppBean();    }}

@Configuration注解应用

Configuration.java

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented// @Component元注解,因而能够被@ComponentScan扫描并解决@Componentpublic @interface Configuration {    @AliasFor(annotation = Component.class)    String value() default "";}

在这里意识几个注解: @Controller, @Service, @Repository, @Component

  • @Controller: 表明一个注解的类是一个"Controller",也就是控制器,能够把它了解为MVC 模式的Controller 这个角色。这个注解是一个非凡的@Component,容许实现类通过类门路的扫描扫描到。它通常与@RequestMapping 注解一起应用。
  • @Service: 表明这个带注解的类是一个"Service",也就是服务层,能够把它了解为MVC 模式中的Service层这个角色,这个注解也是一个非凡的@Component,容许实现类通过类门路的扫描扫描到
  • @Repository: 表明这个注解的类是一个"Repository",团队实现了JavaEE 模式中像是作为"Data Access Object" 可能作为DAO来应用,当与 PersistenceExceptionTranslationPostProcessor 联合应用时,这样正文的类有资格取得Spring转换的目标。这个注解也是@Component 的一个非凡实现,容许实现类可能被主动扫描到
  • @Component: 表明这个正文的类是一个组件,当应用基于正文的配置和类门路扫描时,这些类被视为自动检测的候选者。
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface Controller {    @AliasFor(annotation = Component.class)    String value() default "";}@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface Service {    @AliasFor(annotation = Component.class)    String value() default "";}@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface Repository {    @AliasFor(annotation = Component.class)    String value() default "";}

咱们能够看到@Controller, @Service, @Repository这三个注解上都有@Component这个注解

也就是说,下面四个注解标记的类都可能通过@ComponentScan 扫描到,下面四个注解最大的区别就是应用的场景和语义不一样,比方你定义一个Service类想要被Spring进行治理,你应该把它定义为@Service 而不是@Controller因为咱们从语义上讲,@Service更像是一个服务的类,而不是一个控制器的类,@Component通常被称作组件,它能够标注任何你没有严格予以阐明的类,比如说是一个配置类,它不属于MVC模式的任何一层,这个时候你更习惯于把它定义为 @Component。@Controller,@Service,@Repository 的注解上都有@Component,所以这三个注解都能够用@Component进行替换。

配置类束缚

  • 配置类必须为显式申明的类,而不能通过工厂类办法返回实例。容许运行时类加强。
  • 配置类不容许标记final。
  • 配置类必须全局可见(不容许定义在办法本地外部类中)
  • 嵌套配置类必须申明为static 外部类
  • @Bean办法不能够再创立新的配置类(所有实例都当做bean解决,不解析相干配置注解)

@Configuration源码

ApplicationContext的refresh办法

Spring容器启动时,即ApplicationContext接口实现类的对象实例执行refresh办法时,在Bean初始化实现之前,有一个扩大点,用来操作BeanFactory,来扩大对应的性能,比方往BeanFactory中注册BeanDefintion:

public void refresh() throws BeansException, IllegalStateException {    synchronized (this.startupShutdownMonitor) {        //筹备刷新的上下文 环境        prepareRefresh();        //初始化BeanFactory,并进行XML文件读取        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();        //对beanFactory进行各种性能填充        prepareBeanFactory(beanFactory);        try {            postProcessBeanFactory(beanFactory);            //激活各种beanFactory处理器            invokeBeanFactoryPostProcessors(beanFactory);            //注册拦挡Bean创立的Bean处理器,这里只是注册,真正的调用切实getBean时候            registerBeanPostProcessors(beanFactory);            //为上下文初始化Message源,即不同语言的音讯体,国际化解决            initMessageSource();            //初始化利用音讯播送器,并放入“applicationEventMulticaster”bean中            initApplicationEventMulticaster();            //留给子类来初始化其它的Bean            onRefresh();            //在所有注册的bean中查找Listener bean,注册到音讯播送器中            registerListeners();            //初始化剩下的单实例(非惰性的)            finishBeanFactoryInitialization(beanFactory);            //实现刷新过程,告诉生命周期处理器lifecycleProcessor刷新过程,同时收回ContextRefreshEvent告诉他人            finishRefresh();        }        catch (BeansException ex) {            if (logger.isWarnEnabled()) {                logger.warn("Exception encountered during context initialization - " +                        "cancelling refresh attempt: " + ex);            }            destroyBeans();            cancelRefresh(ex);            throw ex;        }        finally {            resetCommonCaches();        }    }}

invokeBeanFactoryPostProcessors:

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {    // Invoke BeanDefinitionRegistryPostProcessors first, if any.    // 1、首先调用BeanDefinitionRegistryPostProcessors    Set<String> processedBeans = new HashSet<>();    // beanFactory是BeanDefinitionRegistry类型    if (beanFactory instanceof BeanDefinitionRegistry) {        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;        // 定义BeanFactoryPostProcessor        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();        // 定义BeanDefinitionRegistryPostProcessor汇合        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();        // 循环手动注册的beanFactoryPostProcessors        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {            // 如果是BeanDefinitionRegistryPostProcessor的实例话,则调用其postProcessBeanDefinitionRegistry办法,对bean进行注册操作            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {                // 如果是BeanDefinitionRegistryPostProcessor类型,则间接调用其postProcessBeanDefinitionRegistry                BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor;                registryProcessor.postProcessBeanDefinitionRegistry(registry);                registryProcessors.add(registryProcessor);            }            // 否则则将其当做一般的BeanFactoryPostProcessor解决,间接退出regularPostProcessors汇合,以备后续解决            else {                regularPostProcessors.add(postProcessor);            }        }        //略....    }    // 2、如果不是BeanDefinitionRegistry的实例,那么间接调用其回调函数即可-->postProcessBeanFactory    else {        // Invoke factory processors registered with the context instance.        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);    }    //略....}

而ConfigurationClassPostProcessor.java

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {//生成惟一标识,用于反复解决验证   int registryId = System.identityHashCode(registry);   if (this.registriesPostProcessed.contains(registryId)) {      throw new IllegalStateException(            "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);   }   if (this.factoriesPostProcessed.contains(registryId)) {      throw new IllegalStateException(            "postProcessBeanFactory already called on this post-processor against " + registry);   }   this.registriesPostProcessed.add(registryId);   //解析Java类配置bean   processConfigBeanDefinitions(registry);}

processConfigBeanDefinitions(registry):

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {   List<BeanDefinitionHolder> configCandidates = new ArrayList<>();  //所有曾经注册的bean    String[] candidateNames = registry.getBeanDefinitionNames();   //遍历bean定义信息   for (String beanName : candidateNames) {      BeanDefinition beanDef = registry.getBeanDefinition(beanName);      if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||            ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {         if (logger.isDebugEnabled()) {            logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);         }      }    //1.如果以后的bean是Javabean配置类(含有@Configuration注解的类),则退出到汇合configCandidates中,      else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {         configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));      }   }   // Return immediately if no @Configuration classes were found  // 没有@Configuration注解的类,间接退出   if (configCandidates.isEmpty()) {      return;   }   // 多个Java配置类,按@Ordered注解排序   configCandidates.sort((bd1, bd2) -> {      int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());      int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());      return Integer.compare(i1, i2);   });   // Detect any custom bean name generation strategy supplied through the enclosing application context   SingletonBeanRegistry sbr = null;   if (registry instanceof SingletonBeanRegistry) {      sbr = (SingletonBeanRegistry) registry;      if (!this.localBeanNameGeneratorSet) {         BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);         if (generator != null) {            this.componentScanBeanNameGenerator = generator;            this.importBeanNameGenerator = generator;         }      }   }   if (this.environment == null) {      this.environment = new StandardEnvironment();   }   // Parse each @Configuration class  //初始化一个ConfigurationClassParser解析器,能够解析@Congiguration配置类   ConfigurationClassParser parser = new ConfigurationClassParser(         this.metadataReaderFactory, this.problemReporter, this.environment,         this.resourceLoader, this.componentScanBeanNameGenerator, registry);   Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);   Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());   do {   //2.解析Java配置类      parser.parse(candidates);   //次要校验配置类不能应用final修饰符(CGLIB代理是生成一个子类,因而原先的类不能应用final润饰)      parser.validate();      //排除已解决过的配置类      Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());      configClasses.removeAll(alreadyParsed);             // Read the model and create bean definitions based on its content      if (this.reader == null) {         this.reader = new ConfigurationClassBeanDefinitionReader(               registry, this.sourceExtractor, this.resourceLoader, this.environment,               this.importBeanNameGenerator, parser.getImportRegistry());      }    //3.加载bean定义信息,次要实现将@bean @Configuration @Import @ImportResource @ImportRegistrar注册为bean      this.reader.loadBeanDefinitions(configClasses);      alreadyParsed.addAll(configClasses);      //清空已解决的配置类      candidates.clear();   //再次获取容器中bean定义数量  如果大于 之前获取的bean定义数量,则阐明有新的bean注册到容器中,须要再次解析      if (registry.getBeanDefinitionCount() > candidateNames.length) {         String[] newCandidateNames = registry.getBeanDefinitionNames();         Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));         Set<String> alreadyParsedClasses = new HashSet<>();         for (ConfigurationClass configurationClass : alreadyParsed) {            alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());         }         for (String candidateName : newCandidateNames) {            if (!oldCandidateNames.contains(candidateName)) {               BeanDefinition bd = registry.getBeanDefinition(candidateName);        //新注册的bean如果也是@Configuration配置类,则增加到数据,期待解析               if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&                     !alreadyParsedClasses.contains(bd.getBeanClassName())) {                  candidates.add(new BeanDefinitionHolder(bd, candidateName));               }            }         }         candidateNames = newCandidateNames;      }   }   while (!candidates.isEmpty());   // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes   if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {      sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());   }   if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {      // Clear cache in externally provided MetadataReaderFactory; this is a no-op      // for a shared cache since it'll be cleared by the ApplicationContext.      ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();   }}

processConfigBeanDefinitions整个办法能够大体划分为三个阶段:

  1. 从容器中获取和Configuration有关系的BeanDefinition
  2. 以该BeanDefinition为终点,进行解析操作,失去解析后果集
  3. 将解析到的后果集加载到容器中,即结构成一个BeanDefinition放到容器中待初始化

ConfigurationClassUtils.checkConfigurationClassCandidate判断类是否与@Configuration无关

public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {    String className = beanDef.getBeanClassName();    if (className == null || beanDef.getFactoryMethodName() != null) {        return false;    }    //获取注解元数据信息    AnnotationMetadata metadata;    if (beanDef instanceof AnnotatedBeanDefinition &&            className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {        metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();    }    else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {        Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();        metadata = new StandardAnnotationMetadata(beanClass, true);    }    else {        try {            MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);            metadata = metadataReader.getAnnotationMetadata();        }        catch (IOException ex) {            return false;        }    }    // 查找以后注解是否是与@Configuration相干    // 该办法还会判断该注解上的注解是否有@Configuration,始终往上寻找    // 因为有的注解为复合注解    if (isFullConfigurationCandidate(metadata)) {        beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);    }    // 查找以后注解上是否有ComponentScan、Component、Import、ImportResource注解    //如果没有则查找Bean注解,同上,始终往上查找    else if (isLiteConfigurationCandidate(metadata)) {        beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);    }    else {        return false;    }    return true;}

isFullConfigurationCandidate

    public static boolean isFullConfigurationCandidate(AnnotationMetadata metadata) {        return metadata.isAnnotated(Configuration.class.getName());    }

isLiteConfigurationCandidate

    public static boolean isLiteConfigurationCandidate(AnnotationMetadata metadata) {        // Do not consider an interface or an annotation...        if (metadata.isInterface()) {            return false;        }        // Any of the typical annotations found?        for (String indicator : candidateIndicators) {            if (metadata.isAnnotated(indicator)) {                return true;            }        }        // Finally, let's look for @Bean methods...        try {            return metadata.hasAnnotatedMethods(Bean.class.getName());        }        catch (Throwable ex) {            if (logger.isDebugEnabled()) {                logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);            }            return false;        }    }    private static final Set<String> candidateIndicators = new HashSet<>(8);    static {        candidateIndicators.add(Component.class.getName());        candidateIndicators.add(ComponentScan.class.getName());        candidateIndicators.add(Import.class.getName());        candidateIndicators.add(ImportResource.class.getName());    }

解析Java配置类parser.parse(candidates)

parser.parse(candidates)办法最终调用processConfigurationClass办法来解决@Configuration配置类,ConfigurationClassParser. processConfigurationClass()办法实现代码如下

    protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {    //判断是否须要解析        if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {            return;        }    //判断同一个配置类是否反复加载过,如果反复加载过,则合并,否则从汇合中移除旧的配置类,后续逻辑将解决新的配置类        ConfigurationClass existingClass = this.configurationClasses.get(configClass);        if (existingClass != null) {            if (configClass.isImported()) {                if (existingClass.isImported()) {                    existingClass.mergeImportedBy(configClass);                }                // Otherwise ignore new imported config class; existing non-imported class overrides it.                return;            }            else {                // Explicit bean definition found, probably replacing an import.                // Let's remove the old one and go with the new one.                this.configurationClasses.remove(configClass);                this.knownSuperclasses.values().removeIf(configClass::equals);            }        }        // Recursively process the configuration class and its superclass hierarchy.        SourceClass sourceClass = asSourceClass(configClass);        do {      //【真正解析配置类】            sourceClass = doProcessConfigurationClass(configClass, sourceClass);        }        while (sourceClass != null);        //再次增加到到汇合中        this.configurationClasses.put(configClass, configClass);    }

doProcessConfigurationClass办法次要实现从配置类中解析所有bean,包含解决外部类,父类以及各种注解

ConfigurationClassParser. doProcessConfigurationClass()解析配置类逻辑如下:

@Nullable    protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)            throws IOException {        if (configClass.getMetadata().isAnnotated(Component.class.getName())) {            // Recursively process any member (nested) classes first      //递归解决任何成员(嵌套)类            processMemberClasses(configClass, sourceClass);        }        // Process any @PropertySource annotations    // 解决@PropertySource注解        for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(                sourceClass.getMetadata(), PropertySources.class,                org.springframework.context.annotation.PropertySource.class)) {            if (this.environment instanceof ConfigurableEnvironment) {                processPropertySource(propertySource);            }            else {                logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +                        "]. Reason: Environment must implement ConfigurableEnvironment");            }        }        // 解决@ComponentScan    // 获取@ComponentScan注解信息        Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(                sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);        if (!componentScans.isEmpty() &&                !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {            for (AnnotationAttributes componentScan : componentScans) {                // The config class is annotated with @ComponentScan -> perform the scan immediately        // 按@CmponentScan注解扫描bean                Set<BeanDefinitionHolder> scannedBeanDefinitions =                        this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());                // Check the set of scanned definitions for any further config classes and parse recursively if needed        // 遍历扫描出的bean定义是否是配置类bean                for (BeanDefinitionHolder holder : scannedBeanDefinitions) {                    BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();                    if (bdCand == null) {                        bdCand = holder.getBeanDefinition();                    }          //若果扫描出的bean定义是配置类(含有@COnfiguration),则持续调用parse办法,外部再次调用doProcessConfigurationClas(),递归解析                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {                        parse(bdCand.getBeanClassName(), holder.getBeanName());                    }                }            }        }        // Process any @Import annotations        processImports(configClass, sourceClass, getImports(sourceClass), true);        // Process any @ImportResource annotations        AnnotationAttributes importResource =                AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);        if (importResource != null) {            String[] resources = importResource.getStringArray("locations");            Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");            for (String resource : resources) {                String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);                configClass.addImportedResource(resolvedResource, readerClass);            }        }        // Process individual @Bean methods        Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);        for (MethodMetadata methodMetadata : beanMethods) {            configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));        }        // Process default methods on interfaces        processInterfaces(configClass, sourceClass);        // Process superclass, if any        if (sourceClass.getMetadata().hasSuperClass()) {            String superclass = sourceClass.getMetadata().getSuperClassName();            if (superclass != null && !superclass.startsWith("java") &&                    !this.knownSuperclasses.containsKey(superclass)) {                this.knownSuperclasses.put(superclass, configClass);                // Superclass found, return its annotation metadata and recurse                return sourceClass.getSuperClass();            }        }        // No superclass -> processing is complete        return null;    }

@ComponentScan

@ComponentScan注解解析过程

Set<BeanDefinitionHolder> scannedBeanDefinitions =                        this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

@ComponentScan注解解析,从下面的代码能够看出@ComponentScan注解解析通过调用ComponentScanAnnotationParser的parse办法实现,而parse()办法外部解决了一些scanner属性(过滤器设置)和basePackages包名解决,最终通过调用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) {      //依据basePackage加载包下所有java文件,并扫描出所有bean组件            Set<BeanDefinition> candidates = findCandidateComponents(basePackage);      //遍历beandefition            for (BeanDefinition candidate : candidates) {        //解析作用域Scope                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);                }        //通用注解解析到candidate构造中,次要是解决Lazy, primary, DependsOn, Role ,Description这五个注解                if (candidate instanceof AnnotatedBeanDefinition) {                    AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);                }        //查看以后bean是否曾经注册,不存在则注册                if (checkCandidate(beanName, candidate)) {                    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);                    definitionHolder =                            AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);                    beanDefinitions.add(definitionHolder);          // 注册到ioc容器中,次要是一些@Component组件,@Bean注解办法并没有在此处注册,beanname和beandefinition 键值对                    registerBeanDefinition(definitionHolder, this.registry);                }            }        }        return beanDefinitions;    }

而bean定义信息扫描Set<BeanDefinition> candidates = findCandidateComponents(basePackage);最终调用的是ClassPathScanningCandidateComponentProvider.scanCandidateComponents

    private Set<BeanDefinition> scanCandidateComponents(String basePackage) {        Set<BeanDefinition> candidates = new LinkedHashSet<>();        try {      // @ComponentScan("com.gyt.study")包门路解决:packageSearchPath = classpath*:com/gyt/study/**/*.class            String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +                    resolveBasePackage(basePackage) + '/' + this.resourcePattern;      // //获取以后包下所有的class文件            Resource[] resources = getResourcePatternResolver().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 = getMetadataReaderFactory().getMetadataReader(resource);            //依照scanner过滤器过滤,比方配置类自身将被过滤掉,没有@Component等组件注解的类将过滤掉               //蕴含@Component注解的组件将创立BeanDefinition                        if (isCandidateComponent(metadataReader)) {                            ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);                            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;    }

@Bean

Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);办法实现了@Bean办法的解析,但并未将实现bean实例的创立。

    private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) {        AnnotationMetadata original = sourceClass.getMetadata();    //获取所有@Bean注解的办法        Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName());    // 如果配置类中有多个@Bean注解的办法,则排序        if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) {            // Try reading the class file via ASM for deterministic declaration order...            // Unfortunately, the JVM's standard reflection returns methods in arbitrary            // order, even between different runs of the same application on the same JVM.            try {                AnnotationMetadata asm =                        this.metadataReaderFactory.getMetadataReader(original.getClassName()).getAnnotationMetadata();                Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName());                if (asmMethods.size() >= beanMethods.size()) {                    Set<MethodMetadata> selectedMethods = new LinkedHashSet<>(asmMethods.size());                    for (MethodMetadata asmMethod : asmMethods) {                        for (MethodMetadata beanMethod : beanMethods) {                            if (beanMethod.getMethodName().equals(asmMethod.getMethodName())) {                                selectedMethods.add(beanMethod);                                break;                            }                        }                    }                    if (selectedMethods.size() == beanMethods.size()) {                        // All reflection-detected methods found in ASM method set -> proceed                        beanMethods = selectedMethods;                    }                }            }            catch (IOException ex) {                logger.debug("Failed to read class file via ASM for determining @Bean method order", ex);                // No worries, let's continue with the reflection metadata we started with...            }        }        return beanMethods;    }

回到ConfigurationClassPostProcessor#processConfigBeanDefinitions办法,当调用完parse办法之后,能失去一批ConfigurationClass汇合,然而这时候只是获取到,而容器中还没有对应的注册信息,那么接下来就是对这批汇合进行注册解决

  ConfigurationClassBeanDefinitionReader.loadBeanDefinitions()办法的性能就是将之前解析出的configClasses配置类信息中所有配置相干的信息增加到spring的bean定义,次要是配置类中的@Bean注解办法,配置类@ImportResource和@Import(实现ImportBeanDefinitionRegistrar接口方式)的bean注册

ConfigurationClassBeanDefinitionReader.loadBeanDefinitions()办法 实现逻辑如下:

    /**     * Read {@code configurationModel}, registering bean definitions     * with the registry based on its contents.     */    public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {        TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();        for (ConfigurationClass configClass : configurationModel) {            loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);        }    }
    /**     * Read a particular {@link ConfigurationClass}, registering bean definitions     * for the class itself and all of its {@link Bean} methods.     */    private void loadBeanDefinitionsForConfigurationClass(            ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {        if (trackedConditionEvaluator.shouldSkip(configClass)) {            String beanName = configClass.getBeanName();            if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {                this.registry.removeBeanDefinition(beanName);            }            this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());            return;        }    //与@Import注解相干        if (configClass.isImported()) {            registerBeanDefinitionForImportedConfigurationClass(configClass);        }    //将@Bean办法注册为bean        for (BeanMethod beanMethod : configClass.getBeanMethods()) {            loadBeanDefinitionsForBeanMethod(beanMethod);        }        loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());        loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());    }

loadBeanDefinitionsForBeanMethod

private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {    ConfigurationClass configClass = beanMethod.getConfigurationClass();    MethodMetadata metadata = beanMethod.getMetadata();    //获取办法名    String methodName = metadata.getMethodName();    // Do we need to mark the bean as skipped by its condition?    if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {        configClass.skippedBeanMethods.add(methodName);        return;    }    if (configClass.skippedBeanMethods.contains(methodName)) {        return;    }    //获取@Bean注解的元数据信息    AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);    Assert.state(bean != null, "No @Bean annotation attributes");    // Consider name and any aliases    //获取@Bean注解是否有name属性,如@Bean(name = "myBean")    List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));    //默认bean的名称和办法名称雷同,然而如果设置了name,就取name作为beanName    String beanName = (!names.isEmpty() ? names.remove(0) : methodName);    //创立一个BeanMethod的BeanDefinition    ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);    beanDef.setResource(configClass.getResource());    beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));    //设置工厂办法    //前期Bean的实例化,getBean的时候,会判断BeanMethod是否存在FactoryMethod,如果存在,就应用反射调用工厂办法,返回工厂办法中的对象    if (metadata.isStatic()) {        // static @Bean method        beanDef.setBeanClassName(configClass.getMetadata().getClassName());        beanDef.setFactoryMethodName(methodName);    }    else {        // instance @Bean method        beanDef.setFactoryBeanName(configClass.getBeanName());        beanDef.setUniqueFactoryMethodName(methodName);    }    //....    this.registry.registerBeanDefinition(beanName, beanDefToRegister);}

Component注解的派生性原理

https://www.cnblogs.com/liuen...

模式注解

Stereotype Annotation俗称为模式注解。Spring外围局部提供了几种内建的模式注解,如@Component,@Repository,@Service,@Controller,@Configuration等。这些注解均派生于@Component

因为Java语言规定,Annotation不容许继承,没有类派生子类的个性,因而Spring采纳元标注的形式实现注解之间的派生

@Component派生性

@Component注解作为Spring容器托管的通用模式组件,任何被@Component标注的组件均为组件扫描的候选对象。

ClassPathBeanDefinitionScanner#doScan(String... basePackages)调用时,它利用basePackages参数迭代执行的findCandidateComponents(String basePackage),每次执行后果都生成候选的BeanDefinition汇合,即candidates变量。

源码如上
默认状况下,ClassPathScanningCandidateComponentProvider结构参数useDefaultFilters为true,并且显示传递给父类结构参数。该办法给属性includeFilters削减了@Component类型AnnotationTypeFilter的TypeFilter。

registerDefaultFilters

    protected void registerDefaultFilters() {        this.includeFilters.add(new AnnotationTypeFilter(Component.class));        ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();        try {            this.includeFilters.add(new AnnotationTypeFilter(                    ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));            logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");        }        catch (ClassNotFoundException ex) {            // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.        }        try {            this.includeFilters.add(new AnnotationTypeFilter(                    ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));            logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");        }        catch (ClassNotFoundException ex) {            // JSR-330 API not available - simply skip.        }    }

ClassPathBeanDefinitionScanner默认过滤器引入标注@Component,@Repository,@Service或者@Controller等类。同理,它也可能标注所有@Component的"派生"注解。

扩大

利用ClassPathBeanDefinitionScanner类配合includeFiltersexcludeFilters定制化批量注册Bean到Spring容器中。经常能够通过注解形式来蕴含或者排除候选类。

TypeFilter罕用实现

  • AnnotationTypeFilter:注解类型过滤器
  • AssignableTypeFilter:确定此对象示意的类或者接口是否为给定类或者接口雷同。
  • RegexPatternTypeFilter:判断给定的类名是否合乎指定正则表达式。

@AliasFor

@AliasFor 用法: * 用到注解 属性上,示意两个属性相互为别名,相互为别名的属性值必须雷同,若设置成不同,则会报错 * 注解是能够继承的,然而注解是不能继承父注解的属性的,也就是说,我在类扫描的时候,拿到的注解的属性值,仍然是父注解的属性值,而不是你定义的注解的属性值 * 所以此时能够在子注解对应的属性上加上@AliasFor * 

总结

解决逻辑理了一遍后,看一下ConfigurationClassPostProcessor处理器解析@configuration配置类次要过程:

  1. Spring容器初始化时注册默认后置处理器ConfigurationClassPostProcessor

  2. Spring容器初始化执行refresh()办法中调用ConfigurationClassPostProcessor

  3. ConfigurationClassPostProcessor处理器借助ConfigurationClassParser实现配置类解析

  4. ConfigurationClassParser配置内解析过程中实现嵌套的MemberClass、@PropertySource注解、@ComponentScan注解(扫描package下的所有Class并进行迭代解析,次要是@Component组件解析及注册)、@ImportResource、@Bean等解决

  5. 实现@Bean注册, @ImportResource指定bean的注册以及@Import(实现ImportBeanDefinitionRegistrar接口方式)的bean注册

  6.有@Bean注解的办法在解析的时候作为ConfigurationClass的一个属性,最初还是会转换成BeanDefinition进行解决, 而实例化的时候会作为一个工厂办法进行Bean的创立