03、容器創(chuàng)建準(zhǔn)備前期工作

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.class)

一:這行代碼為我們做了什么?

首先AnnotationConfigApplicationContext 繼承了GenericApplicationContext,所以AnnotationConfigApplicationContext 初始化的時(shí)候會(huì)走一下GenericApplicationContext的構(gòu)造函數(shù)。去創(chuàng)建一個(gè)叫做this.beanFactory =new DefaultListableBeanFactory();這樣的默認(rèn)Bean工廠。

父類(lèi)的無(wú)參構(gòu)造器

public GenericApplicationContext() {
        //創(chuàng)建IOC容器
        this.beanFactory = new DefaultListableBeanFactory();
    }

這里為什么會(huì)new一個(gè)DefaultListableBeanFactory,因?yàn)?,DefaultListableBeanFactory這個(gè)類(lèi)是BeanFactory下實(shí)現(xiàn)功能最多的一個(gè)類(lèi)。故此來(lái)構(gòu)建它。

二、AnnotationConfigApplicationContext 構(gòu)造方法都干了些什么?

首先看一下AnnotationConfigApplicationContext 的構(gòu)造函數(shù)

/**
    public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
        //調(diào)用無(wú)參構(gòu)造函數(shù),會(huì)調(diào)用父類(lèi)的無(wú)參構(gòu)造器
        this();
        //注冊(cè)配置類(lèi)
        register(componentClasses);
        //容器刷新
        refresh();
    }

第一步:調(diào)用自己的無(wú)參構(gòu)造

/**
 * Create a new AnnotationConfigApplicationContext that needs to be populated
 * through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
 */
    public AnnotationConfigApplicationContext() {
        this.reader = new AnnotatedBeanDefinitionReader(this);
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

這里有兩個(gè)東西,第一個(gè)是AnnotatedBeanDefinitionReader。注解Bean定義的讀取器,下圖中的構(gòu)造器有個(gè)getOrCreateEnvironment方法,是獲取或者創(chuàng)建一個(gè)環(huán)境,并且加入緩存。

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
    this(registry, getOrCreateEnvironment(registry));
}

回過(guò)頭點(diǎn)開(kāi)this,其中ConditionEvaluator 是@Condition注解的一個(gè)解析器。這個(gè)東西很重要。AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)很重要,重要的不能在重要,敲黑板,劃重點(diǎn)。。。。。

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        this.beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;
        this.scopeMetadataResolver = new AnnotationScopeMetadataResolver();
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        Assert.notNull(environment, "Environment must not be null");
        this.registry = registry;
        this.conditionEvaluator = new ConditionEvaluator(registry, environment, (ResourceLoader)null);
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

點(diǎn)進(jìn)去看一下

public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
        registerAnnotationConfigProcessors(registry, (Object)null);
    }

registerAnnotationConfigProcessors是注解的配置處理器,點(diǎn)進(jìn)去看一下public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, Object source) {}如下圖可知,這個(gè)類(lèi)主要的作用是,將各種各樣不同類(lèi)型的類(lèi)定義,注入到容器當(dāng)中,注意,此時(shí)是Bean的定義并不是真正的創(chuàng)建Bean的實(shí)例到IOC容器中。就比如,洗浴中心要招一批小姐姐,規(guī)定身高180以上,體重120以下,只是定義。僅此而已。如下圖可知,第一個(gè)Bean的定義ConfigurationClassPostProcessor.class。它是通過(guò)internalAutowiredAnnotationProcessor名字進(jìn)行判斷,注入的類(lèi)型是ConfigurationClassPostProcessor。

        Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet(8);
        RootBeanDefinition def;
        if (!registry.containsBeanDefinition("org.springframework.context.annotation.internalConfigurationAnnotationProcessor")) {
            def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"));
        }

        if (!registry.containsBeanDefinition("org.springframework.context.annotation.internalAutowiredAnnotationProcessor")) {
            def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"));
        }

        if (jsr250Present && !registry.containsBeanDefinition("org.springframework.context.annotation.internalCommonAnnotationProcessor")) {
            def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalCommonAnnotationProcessor"));
        }

通過(guò)如下代碼把BeanDefinition注冊(cè)到容器中去:

beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"));

還有如下下圖所示,是解析Autowired自動(dòng)配的

        if (!registry.containsBeanDefinition("org.springframework.context.annotation.internalAutowiredAnnotationProcessor")) {
            def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"));
        }

總結(jié):
registerAnnotationConfigProcessors(registry, (Object)null);的作用就是處理各種內(nèi)部的組件。比如,AutoWired、Required、jsr250標(biāo)準(zhǔn),JPA等等等。。。Bean定義它是用來(lái)描述Bean的,是否是懶加載等等等。

回過(guò)頭在看看第二個(gè)東西AnnotationConfigApplicationContext(類(lèi)路徑下Bean掃描器),它的構(gòu)造方法中的第二句話this.scanner =new ClassPathBeanDefinitionScanner(this);這句話就比較牛逼了。

如下圖所示,我們一直進(jìn)入方法最后一層在類(lèi):ClassPathBeanDefinitionScanner下的ClassPathBeanDefinitionScanner方法中可以看到useDefaultFilters為true執(zhí)行this.registerDefaultFilters();加載默認(rèn)的配置策略。這也是之前的文章講過(guò)的。在包掃描中如果使用includeFilters包含條件的話如果useDefaultFilters設(shè)為false就只會(huì)采用自定義的包掃描規(guī)則,如果為true是全量加載。

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment, @Nullable ResourceLoader resourceLoader) {
        this.beanDefinitionDefaults = new BeanDefinitionDefaults();
        this.beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;
        this.scopeMetadataResolver = new AnnotationScopeMetadataResolver();
        this.includeAnnotationConfig = true;
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        this.registry = registry;
        if (useDefaultFilters) {
            this.registerDefaultFilters();
        }

        this.setEnvironment(environment);
        this.setResourceLoader(resourceLoader);
    }

進(jìn)入this.registerDefaultFilters()方法中
如下圖所示,我的默認(rèn)掃描規(guī)則是包含@Component注解的類(lèi)。比如@Controller、比如@Service、比如@Confingration等等等等注解,如果不符合JSR-250、JSR-330標(biāo)準(zhǔn)就會(huì)拋出異常。

protected void registerDefaultFilters() {
        this.includeFilters.add(new AnnotationTypeFilter(Component.class));
        ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();

        try {
            this.includeFilters.add(new AnnotationTypeFilter(ClassUtils.forName("javax.annotation.ManagedBean", cl), false));
            this.logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
        } catch (ClassNotFoundException var4) {
            ;
        }

        try {
            this.includeFilters.add(new AnnotationTypeFilter(ClassUtils.forName("javax.inject.Named", cl), false));
            this.logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
        } catch (ClassNotFoundException var3) {
            ;
        }

    }

至此如下圖的兩端代碼分析結(jié)束,第一個(gè)的主要作用是,注冊(cè)內(nèi)部的組件(比如:注解配置的處理器)Bean定義到容器中。第二個(gè)是掃描策略。

public AnnotationConfigApplicationContext() {
        this.reader = new AnnotatedBeanDefinitionReader(this);
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

第二步:第二個(gè)方法this.register(annotatedClasses);

/**
    public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
        //調(diào)用無(wú)參構(gòu)造函數(shù),會(huì)調(diào)用父類(lèi)的無(wú)參構(gòu)造器
        this();
        //注冊(cè)配置類(lèi)
        register(componentClasses);
        //容器刷新
        refresh();
    }

拋出結(jié)論:這段代碼就是將我們自己傳入進(jìn)來(lái)的MainConfig類(lèi)注冊(cè)到容器中去。如以下代碼所示,進(jìn)入方法最后找到類(lèi)AnnotatedBeanDefinitionReader中的registerBean方法。前面大概的意思就是說(shuō)看我們的類(lèi)上有沒(méi)有@Primary、@Lazy、這些個(gè)東西。最后通過(guò)BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);這個(gè)方法,將我們的自己配置的類(lèi)(跟容器內(nèi)部的類(lèi)區(qū)別開(kāi))注冊(cè)到容器中。

    private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) {
        AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
        if (!this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
            abd.setInstanceSupplier(supplier);
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
            abd.setScope(scopeMetadata.getScopeName());
            String beanName = name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry);
            AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
            int var10;
            int var11;
            if (qualifiers != null) {
                Class[] var9 = qualifiers;
                var10 = qualifiers.length;

                for(var11 = 0; var11 < var10; ++var11) {
                    Class<? extends Annotation> qualifier = var9[var11];
                    if (Primary.class == qualifier) {
                        abd.setPrimary(true);
                    } else if (Lazy.class == qualifier) {
                        abd.setLazyInit(true);
                    } else {
                        abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                    }
                }
            }

            if (customizers != null) {
                BeanDefinitionCustomizer[] var13 = customizers;
                var10 = customizers.length;

                for(var11 = 0; var11 < var10; ++var11) {
                    BeanDefinitionCustomizer customizer = var13[var11];
                    customizer.customize(abd);
                }
            }

            BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
            definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
            BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
        }
    }

以上this()、register(componentClasses)這兩個(gè)方法分析完畢。

三:this.refresh()

最重要,也是最難理解的一個(gè)方法。無(wú)論是Spring還是SpringBoot都是通過(guò)這個(gè)方法去帶動(dòng)的。故此非常非常之重要。并且這里面的功能多的嚇?biāo)廊?。下面逐一分析?/p>

    public void refresh() throws BeansException, IllegalStateException {
        Object var1 = this.startupShutdownMonitor;
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            this.prepareBeanFactory(beanFactory);

            try {
                this.postProcessBeanFactory(beanFactory);
                this.invokeBeanFactoryPostProcessors(beanFactory);
                this.registerBeanPostProcessors(beanFactory);
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var9) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }

                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }

        }
    }
1,上面說(shuō)過(guò)ConfigurationClassPostProcessor這個(gè)類(lèi)非常的重要,一定要記住它。點(diǎn)進(jìn)來(lái)看一下,如下圖所示。他是BeanDefinitionRegistryPostProcessor類(lèi)型,我們先記住這個(gè)接口
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
    public static final AnnotationBeanNameGenerator IMPORT_BEAN_NAME_GENERATOR = new FullyQualifiedAnnotationBeanNameGenerator();
    private static final String IMPORT_REGISTRY_BEAN_NAME = ConfigurationClassPostProcessor.class.getName() + ".importRegistry";
    private final Log logger = LogFactory.getLog(this.getClass());
    private SourceExtractor sourceExtractor = new PassThroughSourceExtractor();
    private ProblemReporter problemReporter = new FailFastProblemReporter();
    @Nullable
    private Environment environment;
    private ResourceLoader resourceLoader = new DefaultResourceLoader();
    @Nullable
    private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
    private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory();
    private boolean setMetadataReaderFactoryCalled = false;
    private final Set<Integer> registriesPostProcessed = new HashSet();
    private final Set<Integer> factoriesPostProcessed = new HashSet();
    @Nullable
    private ConfigurationClassBeanDefinitionReader reader;
    private boolean localBeanNameGeneratorSet = false;
    private BeanNameGenerator componentScanBeanNameGenerator;
    private BeanNameGenerator importBeanNameGenerator;
}
2,回到refresh()方法中來(lái),看一下如下圖所示,調(diào)用了一個(gè)Bean工廠的后置處理器invokeBeanFactoryPostProcessors(beanFactory);
3,點(diǎn)進(jìn)這個(gè)方法可以看一下,如下圖所示,看第一個(gè)if判斷的是beanFactory是不是Bean的注冊(cè)器。其實(shí)這個(gè) beanFactory就是我們一開(kāi)始構(gòu)建的那個(gè)DefaultListableBeanFactory類(lèi)。那么點(diǎn)進(jìn)這個(gè)類(lèi),會(huì)發(fā)現(xiàn)它屬于bean的注冊(cè)器。
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
        Set<String> processedBeans = new HashSet();
        ArrayList regularPostProcessors;
        ArrayList registryProcessors;
        int var9;
        ArrayList currentRegistryProcessors;
        String[] postProcessorNames;
        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry)beanFactory;
            regularPostProcessors = new ArrayList();
            registryProcessors = new ArrayList();
            Iterator var6 = beanFactoryPostProcessors.iterator();

            while(var6.hasNext()) {
                BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor)var6.next();
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor)postProcessor;
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                } else {
                    regularPostProcessors.add(postProcessor);
                }
            }
    }
}

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable

4,既然是Bean的注冊(cè)器,那么就會(huì)進(jìn)入第一個(gè)if判斷,然后將beanFactory轉(zhuǎn)成Bean的注冊(cè)器,下面有兩個(gè)list。第一個(gè)list可以解釋為普通的PostProcessors,就是非BeanDefinitionRegistryPostProcessor類(lèi)型的list。此時(shí)看while循環(huán),這個(gè)循環(huán)根本就不會(huì)進(jìn)來(lái),因?yàn)閭魅氲腷eanFactoryPostProcessors是一個(gè)半成品,并未有值。是一個(gè)空對(duì)象而已。while循環(huán)里只是做了,對(duì)兩種類(lèi)型的分類(lèi)。并且放到regularPostProcessors和registryProcessors里面去。
if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry)beanFactory;
            regularPostProcessors = new ArrayList();
            registryProcessors = new ArrayList();
            Iterator var6 = beanFactoryPostProcessors.iterator();

            while(var6.hasNext()) {
                BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor)var6.next();
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor)postProcessor;
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                } else {
                    regularPostProcessors.add(postProcessor);
                }
            }
5,再往下看代碼,如圖所示,紅框1內(nèi)表示創(chuàng)建一個(gè)(當(dāng)前正在注冊(cè)的一個(gè)處理器)。再往下看,紅框2,實(shí)際上postProcessorNames數(shù)組就是我們之前在this()中加載的Bean的注冊(cè)器BeanDefinitionRegistryPostProcessor。紅框三中的currentRegistryProcessors.add表示往容器中第一次調(diào)用,放入了一個(gè)Bean并且放入單例緩存池中具體細(xì)節(jié)其他章節(jié)闡述。processedBeans.add(ppName);這句話代表的是將Bean的注冊(cè)器放入方法第一行定義的Set中。其次后面的代碼不重要,重要的是invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);這句話
6,如果沒(méi)invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);這句話,我們自定義的Bean根本就不會(huì)被注冊(cè)進(jìn)來(lái)。點(diǎn)擊進(jìn)入方法內(nèi)。可以看到postProcessors他的類(lèi)型就是前面講的最重要的那個(gè)類(lèi)型ConfigurationClassPostProcessor

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {

private static void invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
        Iterator var2 = postProcessors.iterator();

        while(var2.hasNext()) {
            BeanDefinitionRegistryPostProcessor postProcessor = (BeanDefinitionRegistryPostProcessor)var2.next();
            postProcessor.postProcessBeanDefinitionRegistry(registry);
        }

    }
7,同樣點(diǎn)進(jìn)去看看方法內(nèi),找到ConfigurationClassPostProcessor類(lèi)中postProcessBeanDefinitionRegistry方法看看如何做的。我們主要看最后一行,處理配置Bean定義信息。直接點(diǎn)進(jìn)去
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);
        } else if (this.factoriesPostProcessed.contains(registryId)) {
            throw new IllegalStateException("postProcessBeanFactory already called on this post-processor against " + registry);
        } else {
            this.registriesPostProcessed.add(registryId);
            this.processConfigBeanDefinitions(registry);
        }
    }
9,看下圖中第二個(gè)紅框內(nèi)的代碼,其他的看不懂不要緊,但至少能看懂兩個(gè)東西,第一個(gè)是包掃描的生成器,起一個(gè)名字。第二個(gè)通過(guò)import注解導(dǎo)入的也要起個(gè)名字。
            //@Order注解的排序
            configCandidates.sort((bd1, bd2) -> {
                int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
                int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
                return Integer.compare(i1, i2);
            });
            SingletonBeanRegistry sbr = null;
            if (registry instanceof SingletonBeanRegistry) {
                sbr = (SingletonBeanRegistry)registry;
                if (!this.localBeanNameGeneratorSet) {
                    BeanNameGenerator generator = (BeanNameGenerator)sbr.getSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator");
                    if (generator != null) {
                        this.componentScanBeanNameGenerator = generator;
                        this.importBeanNameGenerator = generator;
                    }
                }
            }

10,接著往下看,如下圖所示通過(guò)注釋可知,這段代碼是對(duì)Bean的配置類(lèi)的解析,創(chuàng)建一個(gè)Bean的解析器。這里使用了一個(gè)do-while循環(huán),其中candidates集合表示候選的,alreadyParsed集合表示已解析的,但是長(zhǎng)度設(shè)為了1.其作用就是使用了do-while循環(huán),肯定先執(zhí)行一次。節(jié)省內(nèi)存。那么最核心的解析代碼是parser.parse(candidates);點(diǎn)進(jìn)去看一下。
            ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry);
            Set<BeanDefinitionHolder> candidates = new LinkedHashSet(configCandidates);
            HashSet alreadyParsed = new HashSet(configCandidates.size());

            do {
                parser.parse(candidates);
                parser.validate();
                Set<ConfigurationClass> configClasses = new LinkedHashSet(parser.getConfigurationClasses());
                configClasses.removeAll(alreadyParsed);
                if (this.reader == null) {
                    this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry());
                }

                this.reader.loadBeanDefinitions(configClasses);
                alreadyParsed.addAll(configClasses);
                candidates.clear();
                if (registry.getBeanDefinitionCount() > candidateNames.length) {
                    String[] newCandidateNames = registry.getBeanDefinitionNames();
                    Set<String> oldCandidateNames = new HashSet(Arrays.asList(candidateNames));
                    Set<String> alreadyParsedClasses = new HashSet();
                    Iterator var12 = alreadyParsed.iterator();

                    while(var12.hasNext()) {
                        ConfigurationClass configurationClass = (ConfigurationClass)var12.next();
                        alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
                    }

                    String[] var23 = newCandidateNames;
                    int var24 = newCandidateNames.length;

                    for(int var14 = 0; var14 < var24; ++var14) {
                        String candidateName = var23[var14];
                        if (!oldCandidateNames.contains(candidateName)) {
                            BeanDefinition bd = registry.getBeanDefinition(candidateName);
                            if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) && !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                                candidates.add(new BeanDefinitionHolder(bd, candidateName));
                            }
                        }
                    }

                    candidateNames = newCandidateNames;
                }
            } while(!candidates.isEmpty());
11,點(diǎn)進(jìn)parse方法,我們的MainClass是通過(guò)注解的形式定義的。所以走AnnotatedBeanDefinition條件的parse方法。點(diǎn)進(jìn)去。
public void parse(Set<BeanDefinitionHolder> configCandidates) {
        Iterator var2 = configCandidates.iterator();

        while(var2.hasNext()) {
            BeanDefinitionHolder holder = (BeanDefinitionHolder)var2.next();
            BeanDefinition bd = holder.getBeanDefinition();

            try {
                if (bd instanceof AnnotatedBeanDefinition) {
                    this.parse(((AnnotatedBeanDefinition)bd).getMetadata(), holder.getBeanName());
                } else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition)bd).hasBeanClass()) {
                    this.parse(((AbstractBeanDefinition)bd).getBeanClass(), holder.getBeanName());
                } else {
                    this.parse(bd.getBeanClassName(), holder.getBeanName());
                }
            } catch (BeanDefinitionStoreException var6) {
                throw var6;
            } catch (Throwable var7) {
                throw new BeanDefinitionStoreException("Failed to parse configuration class [" + bd.getBeanClassName() + "]", var7);
            }
        }

        this.deferredImportSelectorHandler.process();
    }
12,解析配置類(lèi)
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
        this.processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
    }
13,點(diǎn)進(jìn)去以后,其他的都不用看直接看下面,doProcessConfigurationClass這個(gè)代碼。為什么?因?yàn)镾pring真正干活的類(lèi),基本都是以do開(kāi)頭的方法名(小技巧)點(diǎn)進(jìn)去
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
        if (!this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
            ConfigurationClass existingClass = (ConfigurationClass)this.configurationClasses.get(configClass);
            if (existingClass != null) {
                if (configClass.isImported()) {
                    if (existingClass.isImported()) {
                        existingClass.mergeImportedBy(configClass);
                    }

                    return;
                }

                this.configurationClasses.remove(configClass);
                this.knownSuperclasses.values().removeIf(configClass::equals);
            }

            ConfigurationClassParser.SourceClass sourceClass = this.asSourceClass(configClass, filter);

            do {
                sourceClass = this.doProcessConfigurationClass(configClass, sourceClass, filter);
            } while(sourceClass != null);

            this.configurationClasses.put(configClass, configClass);
        }
    }
14,點(diǎn)進(jìn)去我們發(fā)現(xiàn)AnnotationConfigUtils.attributesForRepeatable這個(gè)方法,他是用來(lái)進(jìn)行解析我們的Component注解的。將這個(gè)注解解析成一個(gè)對(duì)象如下圖所示。
protected final ConfigurationClassParser.SourceClass doProcessConfigurationClass(ConfigurationClass configClass, ConfigurationClassParser.SourceClass sourceClass, Predicate<String> filter) throws IOException {
        if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
            this.processMemberClasses(configClass, sourceClass, filter);
        }

        Iterator var4 = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class, PropertySource.class).iterator();

        AnnotationAttributes importResource;
        while(var4.hasNext()) {
            importResource = (AnnotationAttributes)var4.next();
            if (this.environment instanceof ConfigurableEnvironment) {
                this.processPropertySource(importResource);
            } else {
                this.logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment");
            }
        }

        Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
        if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
            Iterator var14 = componentScans.iterator();

            while(var14.hasNext()) {
                AnnotationAttributes componentScan = (AnnotationAttributes)var14.next();
                Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                Iterator var8 = scannedBeanDefinitions.iterator();

                while(var8.hasNext()) {
                    BeanDefinitionHolder holder = (BeanDefinitionHolder)var8.next();
                    BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                    if (bdCand == null) {
                        bdCand = holder.getBeanDefinition();
                    }

                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                        this.parse(bdCand.getBeanClassName(), holder.getBeanName());
                    }
                }
            }
        }

        this.processImports(configClass, sourceClass, this.getImports(sourceClass), filter, true);
        importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
        if (importResource != null) {
            String[] resources = importResource.getStringArray("locations");
            Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
            String[] var20 = resources;
            int var22 = resources.length;

            for(int var23 = 0; var23 < var22; ++var23) {
                String resource = var20[var23];
                String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
                configClass.addImportedResource(resolvedResource, readerClass);
            }
        }

        Set<MethodMetadata> beanMethods = this.retrieveBeanMethodMetadata(sourceClass);
        Iterator var18 = beanMethods.iterator();

        while(var18.hasNext()) {
            MethodMetadata methodMetadata = (MethodMetadata)var18.next();
            configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
        }

        this.processInterfaces(configClass, sourceClass);
        if (sourceClass.getMetadata().hasSuperClass()) {
            String superclass = sourceClass.getMetadata().getSuperClassName();
            if (superclass != null && !superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) {
                this.knownSuperclasses.put(superclass, configClass);
                return sourceClass.getSuperClass();
            }
        }

        return null;
    }
15,下面這段代碼才是真正的對(duì)你的包掃描進(jìn)行解析。上面那點(diǎn),就好比,你發(fā)現(xiàn)了她是一個(gè)小姐姐,下面紅框下的代碼才是真正的對(duì)這個(gè)小姐姐進(jìn)行分析,底盤(pán)扎實(shí)不扎實(shí),發(fā)動(dòng)機(jī)是否好用,變速箱是否換擋順暢等等等一系列的信息。然后我們直接點(diǎn)進(jìn)parse方法看一下
        if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
            Iterator var14 = componentScans.iterator();

            while(var14.hasNext()) {
                AnnotationAttributes componentScan = (AnnotationAttributes)var14.next();
                Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                Iterator var8 = scannedBeanDefinitions.iterator();

                while(var8.hasNext()) {
                    BeanDefinitionHolder holder = (BeanDefinitionHolder)var8.next();
                    BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                    if (bdCand == null) {
                        bdCand = holder.getBeanDefinition();
                    }

                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                        this.parse(bdCand.getBeanClassName(), holder.getBeanName());
                    }
                }
            }
        }

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

16,進(jìn)入parse方法以后可以看到創(chuàng)建了一個(gè)掃描器。ClassPathBeanDefinitionScanner scanner =new ClassPathBeanDefinitionScanner(this.registry, componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);然后,把上面解析的Component的值摟出來(lái),逐一的給掃描器賦值進(jìn)行初始化,真正干活的方法是最后的的這句:return scanner.doScan(StringUtils.toStringArray(basePackages));
17,通過(guò)下面的代碼可知找到候選的一個(gè)組件。并且給我們拼接路徑,找到這個(gè)包下所有子包的類(lèi),并且轉(zhuǎn)換成Resource,并且里面存儲(chǔ)的就是我們自己想要的組件。然后循環(huán)resource,判斷是不是可讀的,然后轉(zhuǎn)換成一個(gè)原信息的讀取器。到這里僅僅是將我們的Bean定義掃描到容器中去,并不是Bean的實(shí)例化。接著判斷是否有包含或者排除的組件。接下來(lái)往下執(zhí)行,如果遇到@Controller的組件,就會(huì)進(jìn)行賦值。因?yàn)锧Controller是可讀的。此方法執(zhí)行完畢以后回到doScan方法。進(jìn)行循環(huán)


18,此時(shí)可以看到容器中并沒(méi)有我們自己的組件,但是解析包掃描是找到的。然后接著往下看。原來(lái)是6個(gè)?,F(xiàn)在還是6個(gè)
19,執(zhí)行完registerBeanDefinition(definitionHolder, this.registry);注冊(cè)Bean掃描器以后我們自己定義的組件就被掃描出來(lái)了。doScan執(zhí)行完以后回到this.componentScanParser.parse這個(gè)地方。
20,在this.componentScanParser.parse的最下面又執(zhí)行了一次parse,它作用是掃描比如在@Controller注解上有沒(méi)有其他ComponentScan注解。正常的邏輯是不會(huì)有的。所以這個(gè)功能有點(diǎn)兒多余,不清楚為什么要這么設(shè)計(jì)。
21,代碼繼續(xù)往下走,執(zhí)行這句話processImports。解析完可讀的注解以后,在繼續(xù)掃描類(lèi)上面有沒(méi)有import注解,如果有,就進(jìn)去,并且找到import注解的value值。并且判斷是否是導(dǎo)入的ImportSelector或者是ImportBeanDefinitionRegistrar?;蛘呤荄eferredImportSelector這種類(lèi)型(這個(gè)東西很重要,自動(dòng)注入,SpringBoot進(jìn)行自動(dòng)注入就是通過(guò)這個(gè)東西進(jìn)行處理的)進(jìn)行保存。保存之后就會(huì)有調(diào)用
22,processImports執(zhí)行完以后往下看找到// Process individual @Bean methods,點(diǎn)擊去之后發(fā)現(xiàn),這個(gè)段代碼的意思是,是解析@Bean標(biāo)注的方法。最后執(zhí)行完,回到parse方法。
23,這是我們新掃描出來(lái)的兩個(gè)Bean的定義接著往下看
24,這個(gè)方法很重要。如果說(shuō)在你的@Bean注解標(biāo)注的方法內(nèi)創(chuàng)建了一個(gè)類(lèi)的實(shí)例,在未執(zhí)行此方法的時(shí)候,那么那個(gè)實(shí)例是不會(huì)被加入到Bean定義注冊(cè)器的,只有執(zhí)行了這個(gè)方法以后才會(huì)在Bean的注冊(cè)器中被注冊(cè)??梢酝茢啵@個(gè)方法就是用來(lái)將@Bean標(biāo)注的方法內(nèi)實(shí)例化的對(duì)象摟出來(lái),放入Bean自定義的注冊(cè)器中。并且如果是Import導(dǎo)入的類(lèi),也會(huì)將該類(lèi)加入Bean的自定注冊(cè)器中去,點(diǎn)開(kāi)源碼看。
25,this.reader.loadBeanDefinitions(configClasses);點(diǎn)開(kāi)源碼發(fā)現(xiàn)。通過(guò)import注解導(dǎo)入的類(lèi)會(huì)通過(guò)紅框內(nèi)的方法進(jìn)行注冊(cè),點(diǎn)進(jìn)去看一下
26,進(jìn)入這個(gè)方法以后,這個(gè)方法獲取了你的方法名,這也是為什么Bean的依賴(lài)注入如果不指定別名,就是默認(rèn)的方法名的原因。還進(jìn)行了一系列的判斷,接著往下看。
27,在方法的最后調(diào)用了this.registry.registerBeanDefinition(beanName, beanDefToRegister);方法。這段代碼最關(guān)鍵。執(zhí)行完以后會(huì)發(fā)現(xiàn),@Bean注解標(biāo)注的方法內(nèi),如果通過(guò)new關(guān)鍵字實(shí)例化的對(duì)象,此時(shí)已經(jīng)被加入Bean定義注冊(cè)器當(dāng)中了。是不是很神奇?
image

28,回過(guò)頭總結(jié)一下

  • parser.parse(candidates);這句話僅僅是注冊(cè)包掃描的。
  • this.reader.loadBeanDefinitions(configClasses);這段代碼是加載通過(guò)@import、@ Bean倒進(jìn)來(lái)的。同理,SpringBoot也是通過(guò)這個(gè)東東來(lái)掃描各大裝配種類(lèi)的。

后面的代碼是判斷有沒(méi)有解析完??纯从袥](méi)有,沒(méi)有解析的類(lèi)。一筆帶過(guò)了。如果都解析過(guò),do-while循環(huán)就結(jié)束了。至此下圖所示的一個(gè)方法就分析完畢了。


refresh中的 invokeBeanFactoryPostProcessors(beanFactory);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容