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)中了。是不是很神奇?

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è)方法就分析完畢了。

