我的想寫《springboot源碼解析》這一系列好久了,可是一直角兒心底的知識積累不足,因此一直沒有動筆。 因此想找一些小夥伴一塊兒寫這一系列,互相糾錯交流學習。 若是有小夥伴有興趣一塊兒把這一系列的講解寫完的話,加下我微信:13670426148,咱們一塊兒完成,當交流學習。 後期還想寫一系列介紹rpc框架的,不過要再過一陣子了,先把springboot的寫完java
直接講了 refresh()
的代碼實現,直到完成配置類的實例化爲止,後面的registerBeanPostProcessors
方法還沒開始講。spring
public void refresh() throws BeansException, IllegalStateException {
//由於該過程必須是同步的,因此進行加鎖處理
synchronized(this.startupShutdownMonitor) {
// 1. 容器刷新前的準備,設置上下文,獲取屬性,驗證必要的屬性
this.prepareRefresh();
// 2. 銷燬原先的 beanFactory,建立新的bean工廠,
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
// 3. 配置標準的beanFactory,設置ClassLoader,設置SpEL表達式解析器等等
this.prepareBeanFactory(beanFactory);
try {
// 4. 添加一個BeanPostProcessor到bean工廠中,類型爲WebApplicationContextServletContextAwareProcessor(this)
// 任意Bean均可以很方便的獲取到ServletContext。
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();
}
}
}
複製代碼
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (this.logger.isDebugEnabled()) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Refreshing " + this);
} else {
this.logger.debug("Refreshing " + this.getDisplayName());
}
}
// 初始化 propertySources
this.initPropertySources();
//getEnvironment 得到的是 StandardEnvironment
//檢驗屬性的合法等
this.getEnvironment().validateRequiredProperties();
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new
// 此時的監聽器有12個了,以下圖1.1所示
LinkedHashSet(this.applicationListeners);
} else {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// 默認是一個空的set
this.earlyApplicationEvents = new LinkedHashSet();
}
複製代碼
圖1.1 : 編程
兩步,第一步建立新的beanFactory,第二步是進行基本的配置數組
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//在application中建立DefaultListableBeanFactory並賦值給上下文中的this.beanFactory,至關於原先那個不要了,建立一個新的.
this.refreshBeanFactory();
return this.getBeanFactory();
}
複製代碼
其中refreshBeanFactory()方法是經過 GenericApplicationContext
來執行的這個springboot
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
// 構造器裏面就建立了DefaultListableBeanFactory了
public GenericApplicationContext() {
this.customClassLoader = false;
this.refreshed = new AtomicBoolean();
this.beanFactory = new DefaultListableBeanFactory();
}
//
protected final void refreshBeanFactory() throws IllegalStateException {
if (!this.refreshed.compareAndSet(false, true)) {
throw new IllegalStateException("GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
} else {
this.beanFactory.setSerializationId(this.getId());
}
}
}
複製代碼
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 設置beanFactory的classLoader爲當前context的classLoader
beanFactory.setBeanClassLoader(this.getClassLoader());
// 設置EL表達式解析器(Bean初始化完成後填充屬性時會用到)
// spring3增長了表達式語言的支持,默承認以使用#{bean.xxx}的形式來調用相關屬性值
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
// 設置屬性註冊解析器PropertyEditor 這個主要是對bean的屬性等設置管理的一個工具
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
// 將當前的ApplicationContext對象交給ApplicationContextAwareProcessor類來處理,從而在Aware接口實現類中的注入applicationContext等等
// 添加了一個處理aware相關接口的beanPostProcessor擴展,主要是使用beanPostProcessor的postProcessBeforeInitialization()前置處理方法實現aware相關接口的功能
// 相似的還有ResourceLoaderAware、ServletContextAware等等等等
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 下面是忽略的自動裝配(也就是實現了這些接口的Bean,不要Autowired自動裝配了)
// 默認只有BeanFactoryAware被忽略,因此其它的須要自行設置
// 由於ApplicationContextAwareProcessor把這5個接口的實現工做作了
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 注入一些其它信息的bean,好比environment、systemProperties、SystemEnvironment等
if (beanFactory.containsBean("loadTimeWeaver")) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
if (!beanFactory.containsLocalBean("environment")) {
beanFactory.registerSingleton("environment", this.getEnvironment());
}
if (!beanFactory.containsLocalBean("systemProperties")) {
beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean("systemEnvironment")) {
beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment());
}
}
複製代碼
DefaultListableBeanFactory
的父類 AbstractBeanFactory
中有 List<BeanPostProcessor> beanPostProcessors
此時beanPostProcessors中的內容有 圖1.2: bash
而 DefaultListableBeanFactory
中存在的是 beanDefinitionMap
和 resolvableDependencies
和 beanDefinitionNames
和 manualSingletonNames
微信
beanDefinitionNames
記錄了建立了的beanDefinition的類型集合,beanDefinitionMap存放的是beanDefinition映射。迄今爲止已經存在的有: 圖1.3 app
而registerSingleton
是在 DefaultSingletonBeanRegistry
類中的框架
//先看DefaultListableBeanFactory的registerSingleton方法:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
super.registerSingleton(beanName, singletonObject);
if (this.hasBeanCreationStarted()) {
synchronized(this.beanDefinitionMap) {
if (!this.beanDefinitionMap.containsKey(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet(this.manualSingletonNames.size() + 1);
updatedSingletons.addAll(this.manualSingletonNames);
updatedSingletons.add(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
} else if (!this.beanDefinitionMap.containsKey(beanName)) {
// manualSingletonNames存放已經實例化好單例對象
this.manualSingletonNames.add(beanName);
}
this.clearByTypeCache();
}
}
複製代碼
public class DefaultSingletonBeanRegistry {
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
Assert.notNull(beanName, "Bean name must not be null");
Assert.notNull(singletonObject, "Singleton object must not be null");
synchronized(this.singletonObjects) {
Object oldObject = this.singletonObjects.get(beanName);
if (oldObject != null) {
throw new IllegalStateException("Could not register object [" + singletonObject + "] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
} else {
this.addSingleton(beanName, singletonObject);
}
}
}
protected void addSingleton(String beanName, Object singletonObject) {
//這個是直接實例化了
synchronized(this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
複製代碼
他們之間的差異是,bean先讀取到 beanDefinition中,等到統一實例化的時候,再根據beanDefinition的信息,調用DefaultSingletonBeanRegistry類的registerSingleton方法註冊bean到 beanFactory中。在這裏面涉及到的類有 DefaultSingletonBeanRegistry
、 DefaultListableBeanFactory
和 AbstractBeanFactory
工具
不得不說「單一職責原則」在這裏體現的挺充分的,每一個類都有各自的意義。
添加一個BeanPostProcessor到bean工廠中,類型爲WebApplicationContextServletContextAwareProcessor(this) 任意Bean均可以很方便的獲取到ServletContext。 postProcessBeanFactory方法是父類AnnotationConfigServletWebServerApplicationContext
中的
public class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContext implements AnnotationConfigRegistry {
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//調用父類ServletWebServerApplicationContext的postProcessBeanFactory方法
super.postProcessBeanFactory(beanFactory);
if (this.basePackages != null && this.basePackages.length > 0) {
this.scanner.scan(this.basePackages);
}
if (!this.annotatedClasses.isEmpty()) {
this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
}
}
}
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 添加到AbstractBeanFactory的List<BeanPostProcessors>中
// 註冊ServletContextAwareProcessor 這樣任意Bean均可以很方便的獲取到ServletContext了 同時忽略ServletContextAware,由於ServletContextAwareProcessor 都把事情都作了
beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
this.registerWebApplicationScopes();
}
複製代碼
到了如今 AbstractBeanFactory
中的 BeanPostProcessors
有3個了.
invokeBeanFactoryPostProcessors
方法是在AbstractApplicationContext.class
中實現的
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
public void refresh() throws BeansException, IllegalStateException {
...
//此時beanFactory是DefaultListableBeanFactory
this.invokeBeanFactoryPostProcessors(beanFactory);
...
}
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
//this.getBeanFactoryPostProcessors(),得到到的是BeanFactoryPostProcessors跟上一步的BeanPostProcessors不同
// 交給PostProcessorRegistration處理
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean("loadTimeWeaver")) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
}
複製代碼
BeanFactoryPostProcessors 跟上一步的 BeanPostProcessors 不同
BeanFactoryPostProcessors
是存放在AbstractApplicationContext
中BeanPostProcessors
是存放在AbstractBeanFactory
中的。//Delegate是一個解析器,不少都會這麼操做,把一些任務交給一個解析器去完成
final class PostProcessorRegistrationDelegate {
//此時獲取到的後置處理器有3個, 查看圖1.5
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
Set<String> processedBeans = new HashSet();
// 此處安放了兩個容器,一個裝載普通的BeanFactoryPostProcessor
// 另一個裝載和Bean定義有關的 BeanDefinitionRegistryPostProcessor
// 差異就是BeanDefinitionRegistryPostProcessor裏面多了一個postProcessBeanDefinitionRegistry方法,能夠用來註冊bean的
ArrayList regularPostProcessors;
ArrayList registryProcessors;
int var9;
ArrayList currentRegistryProcessors;
String[] postProcessorNames;
// 確定是要BeanDefinitionRegistry的子類纔會執行下面的內容
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();
// 分別裝成registryProcessors 或者 普通的regularPostProcessors
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor)postProcessor;
//1. 若是是bean定義有關的BeanDefinitionRegistryPostProcessor的話還要先執行其postProcessBeanDefinitionRegistry
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
} else {
regularPostProcessors.add(postProcessor);
}
}
currentRegistryProcessors = new ArrayList();
//這裏獲得的是String : org.springframework.context.annotation.internalConfigurationAnnotationProcessor
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
String[] var16 = postProcessorNames;
var9 = postProcessorNames.length;
int var10;
String ppName;
for(var10 = 0; var10 < var9; ++var10) {
ppName = var16[var10];
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// currentRegistryProcessors裏面是 ConfigurationClassPostPorcessor,一個用來處理 Configuration註解或者Component註解等的後置處理器,很重要
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 添加到registryProcessors中,此時registryProcessors中會有3個BeanDefinitionRegistryPostProcessor(通常狀況下,若是不本身定義的話)
registryProcessors.addAll(currentRegistryProcessors);
// 2. 此時執行ConfigurationClassPostPorcessor的解析操做,找到掃描包下全部的配置類
// currentRegistryProcessors下面通常狀況下只有1個 ConfiguraionClassPostProcessor
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 執行完以後, currentRegistryProcessors清空掉
currentRegistryProcessors.clear();
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
var16 = postProcessorNames;
var9 = postProcessorNames.length;
for(var10 = 0; var10 < var9; ++var10) {
ppName = var16[var10];
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
boolean reiterate = true;
while(reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
String[] var19 = postProcessorNames;
var10 = postProcessorNames.length;
for(int var26 = 0; var26 < var10; ++var26) {
String ppName = var19[var26];
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
invokeBeanFactoryPostProcessors((Collection)registryProcessors, (ConfigurableListableBeanFactory)beanFactory);
invokeBeanFactoryPostProcessors((Collection)regularPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
} else {
invokeBeanFactoryPostProcessors((Collection)beanFactoryPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
}
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
regularPostProcessors = new ArrayList();
registryProcessors = new ArrayList();
currentRegistryProcessors = new ArrayList();
postProcessorNames = postProcessorNames;
int var20 = postProcessorNames.length;
String ppName;
for(var9 = 0; var9 < var20; ++var9) {
ppName = postProcessorNames[var9];
if (!processedBeans.contains(ppName)) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
regularPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
} else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
registryProcessors.add(ppName);
} else {
currentRegistryProcessors.add(ppName);
}
}
}
sortPostProcessors(regularPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors((Collection)regularPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList();
Iterator var21 = registryProcessors.iterator();
while(var21.hasNext()) {
String postProcessorName = (String)var21.next();
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors((Collection)orderedPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList();
Iterator var24 = currentRegistryProcessors.iterator();
while(var24.hasNext()) {
ppName = (String)var24.next();
nonOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors((Collection)nonOrderedPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
beanFactory.clearMetadataCache();
}
}
複製代碼
圖1.5:
裏面總共有2個bean定義有關的後置處理器,第一個是 CachingMetadataReaderFactoryPostProcessor
, 第二個是 ConfigurationWarningsApplicationContextInitializer
private static class CachingMetadataReaderFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {
private CachingMetadataReaderFactoryPostProcessor() {
}
public int getOrder() {
return -2147483648;
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// 在註冊表中註冊SharedMetadataReaderFactoryBean的BeanDefinition
// registry.registerBeanDefinition("org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory", definition);
// definition是包裝了SharedMetadataReaderFactoryContextInitializer.SharedMetadataReaderFactoryBean.class的bean, 再執行 beanDefinitionMap.put("org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory", definition)
this.register(registry);
this.configureConfigurationClassPostProcessor(registry);
}
private void register(BeanDefinitionRegistry registry) {
// 用BeanDefinitionBuilder.genericBeanDefinition()方法,該方法是定義一個BeanDefinition, 這裏是SharedMetadataReaderFactoryBean
BeanDefinition definition = BeanDefinitionBuilder.genericBeanDefinition(SharedMetadataReaderFactoryContextInitializer.SharedMetadataReaderFactoryBean.class, SharedMetadataReaderFactoryContextInitializer.SharedMetadataReaderFactoryBean::new).getBeanDefinition();
// 在註冊表裏面註冊該bean信息,
// internalCachingMetadataReaderFactory -> 這裏是 BeanDefinition
registry.registerBeanDefinition("org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory", definition);
}
// 把一步註冊到註冊表中的 SharedMetadataReaderFactoryBean設置到 internalConfigurationAnnotationProcessor對應的BeanDefinition的 實例的metadataReaderFactory屬性中
private void configureConfigurationClassPostProcessor(BeanDefinitionRegistry registry) {
try {
// 獲取internalConfigurationAnnotationProcessor這個bean,以後設置其屬性metadataReaderFactory的值爲類: org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory
// 此時definition是ConfigurationClassPostProcessor
BeanDefinition definition = registry.getBeanDefinition("org.springframework.context.annotation.internalConfigurationAnnotationProcessor");
// 一個definition的propertyValues裏面就是定義了他實例時候的屬性的值,此時至關於給ConfigurationClassPostProcessor 的metadataReaderFactory屬性設置爲咱們上一步定義的internalCachingMetadataReaderFactory。
definition.getPropertyValues().add("metadataReaderFactory", new RuntimeBeanReference("org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory"));
} catch (NoSuchBeanDefinitionException var3) {
}
}
}
// 第二個後置處理器是
// 作警告。
public class ConfigurationWarningsApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
// registry永遠都是DefaultListableBeanFactory
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
//此時 this.checks是一個數組,裏面的元素只有1個
//ConfigurationWarningsApplicationContextInitializer.ComponentScanPackageCheck
ConfigurationWarningsApplicationContextInitializer.Check[] var2 = this.checks;
int var3 = var2.length;
for(int var4 = 0; var4 < var3; ++var4) {
ConfigurationWarningsApplicationContextInitializer.Check check = var2[var4];
String message = check.getWarning(registry);
// 只是進行警告,若是沒有找到掃描路徑,則會作警告
if (StringUtils.hasLength(message)) {
this.warn(message);
}
}
}
}
protected static class ComponentScanPackageCheck implements ConfigurationWarningsApplicationContextInitializer.Check {
private static final Set<String> PROBLEM_PACKAGES;
protected ComponentScanPackageCheck() {
}
public String getWarning(BeanDefinitionRegistry registry) {
// 下面解釋
Set<String> scannedPackages = this.getComponentScanningPackages(registry);
List<String> problematicPackages = this.getProblematicPackages(scannedPackages);
//能夠看到此時只是返回信息,而不是真的存儲起來.
return problematicPackages.isEmpty() ? null : "Your ApplicationContext is unlikely to start due to a @ComponentScan of " + StringUtils.collectionToDelimitedString(problematicPackages, ", ") + ".";
}
}
public class ConfigurationWarningsApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
protected Set<String> getComponentScanningPackages(BeanDefinitionRegistry registry) {
Set<String> packages = new LinkedHashSet();
// 得到至今爲止全部的註冊表中的Definitions中的Name集合,此時是7個,見圖5.2
String[] names = registry.getBeanDefinitionNames();
String[] var4 = names;
int var5 = names.length;
for(int var6 = 0; var6 < var5; ++var6) {
String name = var4[var6];
BeanDefinition definition = registry.getBeanDefinition(name);
//判斷是什麼類型的 AnnotatedBeanDefinition,
//這個比較重要了,由於以下圖除了啓動入口類(啓動入口類上通常定義了包掃描的路徑,而我項目中的啓動入口類是MallApplication.class)以外全部的都不是AnnotatedBeanDefinition的子類: AnnotatedGenericBeanDefinition
if (definition instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annotatedDefinition = (AnnotatedBeanDefinition)definition;
// annotatedDefinition中Metadata的內容中就有其@ComponentScan註解的信息
this.addComponentScanningPackages(packages, annotatedDefinition.getMetadata());
}
}
return packages;
}
}
protected Set<String> getComponentScanningPackages(BeanDefinitionRegistry registry) {
Set<String> packages = new LinkedHashSet();
String[] names = registry.getBeanDefinitionNames();
String[] var4 = names;
int var5 = names.length;
for(int var6 = 0; var6 < var5; ++var6) {
String name = var4[var6];
BeanDefinition definition = registry.getBeanDefinition(name);
if (definition instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annotatedDefinition = (AnnotatedBeanDefinition)definition;
// 獲取其beanDefinition的信息
this.addComponentScanningPackages(packages, annotatedDefinition.getMetadata());
}
}
// 像我項目這裏獲得的就是入口類的包路徑。
return packages;
}
// 獲取掃描的包路徑
private void addComponentScanningPackages(Set<String> packages, AnnotationMetadata metadata) {
//信息如圖5.3所示
AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(ComponentScan.class.getName(), true));
if (attributes != null) {
this.addPackages(packages, attributes.getStringArray("value"));
this.addPackages(packages, attributes.getStringArray("basePackages"));
this.addClasses(packages, attributes.getStringArray("basePackageClasses"));
//若是都找不到的話,直接找到該bean的包路徑
if (packages.isEmpty()) {
packages.add(ClassUtils.getPackageName(metadata.getClassName()));
}
}
}
複製代碼
//此時postProcessors是ConfigurationClassPostPorcessor
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);
}
}
複製代碼
仍是執行 ConfigurationClassPostProcessor
的 processConfigBeanDefinitions()
方法
圖1.7:
//重點 : 開始解析配置類信息
解釋一下,先找到DefaultListableBeanFactory 裏面已經有了的BeanDefinition,判斷他們是否爲配置類,找到其中全部的配置類,找到其是否有@ComponentScan中掃描的包路徑。
public class ConfigurationClassPostProcessor {
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList();
// 獲取全部已經註冊的beanDefinition的名稱, 這裏是7個,如上圖1.7所示
String[] candidateNames = registry.getBeanDefinitionNames();
String[] var4 = candidateNames;
int var5 = candidateNames.length;
for(int var6 = 0; var6 < var5; ++var6) {
String beanName = var4[var6];
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
// 1.1 若是BeanDefinition 中的configurationClass 屬性爲full 或者lite ,則意味着已經處理過了,直接跳過
if (!ConfigurationClassUtils.isFullConfigurationClass(beanDef) && !ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
// 1.2 判斷對應bean是否爲配置類,若是是,則加入到configCandidates.
// 怎麼判斷是不是配置類呢,下面解析
if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
//-----此時只有入口類 MallApplication 添加進來了, 把是配置類的BeanDefinitionHolder存進來到configCandidates中
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
} else if (this.logger.isDebugEnabled()) {
this.logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
if (!configCandidates.isEmpty()) {
//對配置類BeanDefinitionHolder排序
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
SingletonBeanRegistry sbr = null;
// registry仍是 DefualtListableBeanFactory
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;
}
}
}
// environment已是StandardServletEnvironment 了
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// 交給ConfigurationClassParser去處理,拿到配置類下的 @ComponentScan註解指定的掃描包路徑
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 {
//通常狀況下candidates初始是啓動入口類,在我本地項目調試是MallApplication.class,上面有@SpringApplication註解,該註解裏面默認存在了 @ComponentScan註解
// parser的類型是 ConfigurationClassParser
// 最終要的內容全在這裏面
// 1.3. parse開始解析,把解析方法交給了 ConfigurationClassParser 去解析(下面講解)
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());
}
// 註冊解析到的bean
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.clear();
// candidateNames.length是未解析以前Bean的數量
// registry.getBeanDefinitionCount()是如今Bean的數量
// 主要是以Bean數量判斷是否有新的Bean註冊到IOC容器中去了
// 也就是說,這裏開始操做那些,新註冊進來的Bean
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());
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
((CachingMetadataReaderFactory)this.metadataReaderFactory).clearCache();
}
}
}
}
複製代碼
ConfigurationClassUtils.checkConfigurationClassCandidate
//1.2 檢查對應bean是否爲配置類
abstract class ConfigurationClassUtils {
public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
//1. 獲取類名
String className = beanDef.getBeanClassName();
if (className != null && beanDef.getFactoryMethodName() == null) {
Object metadata;
//2. 若是BeanDefinition 是 AnnotatedBeanDefinition的實例,而且className 和 BeanDefinition中 的元數據 的類名相同
// 則直接從BeanDefinition 得到Metadata
if (beanDef instanceof AnnotatedBeanDefinition && className.equals(((AnnotatedBeanDefinition)beanDef).getMetadata().getClassName())) {
metadata = ((AnnotatedBeanDefinition)beanDef).getMetadata();
} else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition)beanDef).hasBeanClass()) {
// 若是BeanDefinition 是 AnnotatedBeanDefinition的實例,而且beanDef 有 beanClass 屬性存在
// 則實例化StandardAnnotationMetadata
Class<?> beanClass = ((AbstractBeanDefinition)beanDef).getBeanClass();
metadata = new StandardAnnotationMetadata(beanClass, true);
} else {
try {
/// 2.3 不然 經過MetadataReaderFactory 中的MetadataReader 進行讀取
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
metadata = metadataReader.getAnnotationMetadata();
} catch (IOException var5) {
if (logger.isDebugEnabled()) {
logger.debug("Could not find class file for introspecting configuration annotations: " + className, var5);
}
return false;
}
}
//3. 前兩步的內容不重要,重要的是下面
// 這一步設置了lite跟full,跟前面對應起來
//3.1 若是存在@Configuration 註解,則爲BeanDefinition 設置configurationClass屬性爲full
if (isFullConfigurationCandidate((AnnotationMetadata)metadata)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, "full");
} else {
// 若是AnnotationMetadata 中有 @Component, @ComponentScan, @Import, @ImportResource 註解中的任意一個,或者存在 被@bean 註解的方法,則返回true.
// 則設置configurationClass屬性爲lite,
if (!isLiteConfigurationCandidate((AnnotationMetadata)metadata)) {
return false;
}
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, "lite");
}
// 4. 若是該類被@Order所註解,則設置order屬性爲@Order的值
Integer order = getOrder((AnnotationMetadata)metadata);
if (order != null) {
beanDef.setAttribute(ORDER_ATTRIBUTE, order);
}
return true;
} else {
return false;
}
}
}
複製代碼
//class : 交給ConfigurationClassParser
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();
}
//metadata裏面是註解的信息
// 這個時候確定對AnnotationMetadata不太熟悉了,AnnotationMetadata是Spring自定義的註解,它繼承了AnnotatedTypeMetadata
// 而AnnotatedTypeMetadata是對註解元素的封裝適配,裏面內置了一些靈活可用的方法,好比getAnnotationAttributes,isAnnotated
// getAnnotationAttributes()能夠直接判獲取一個註解中值,封裝成一個Map,isAnnotated()判斷是否存在某個註解
// 詳細能夠參考一位大神的講解 https://fangshixiang.blog.csdn.net/article/details/88765470
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
this.processConfigurationClass(new ConfigurationClass(metadata, beanName));
}
// 看看ConfigurationClass的構造器
// public ConfigurationClass(AnnotationMetadata metadata, String beanName) {
// Assert.notNull(beanName, "Bean name must not be null");
// this.metadata = metadata;
// this.resource = new DescriptiveResource(metadata.getClassName());
// this.beanName = beanName;}
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
// 1.1. 判斷是否應該跳過
if (!this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
// 1.2. 處理 Imported的狀況,暫時無論
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);
}
// 格式如圖1.8所示
// 那麼什麼是SourceClass 呢
// 它是對source對象一個輕量級的包裝,持有AnnotationMetadata 元數據,以下通常實際爲一個
// 看到裏面 SourceClass的構造器
//public SourceClass(Object source) {
//this.source = source;
//if (source instanceof Class) {
// this.metadata = new StandardAnnotationMetadata((Class<?>) source, true);
//} else {
// this.metadata = ((MetadataReader) source).getAnnotationMetadata();
//}
//}
ConfigurationClassParser.SourceClass sourceClass = this.asSourceClass(configClass);
do {
//1.3. 遞歸調用進行解析,最終的解析,
// 由於一個配置類,好比 入口類,可能會有父類,那麼這些類指定的掃描仍是得繼續進行掃描,因此遞歸調用了。
sourceClass = this.doProcessConfigurationClass(configClass, sourceClass);
} while(sourceClass != null);
// 1.4. 添加到cinfigurationClasses中
this.configurationClasses.put(configClass, configClass);
}
}
//1.3 遞歸調用進行解析,最終的解析
//通常狀況下一開始configClass是 入口類上的註解,也就是 @SpringbootApplication
protected final ConfigurationClassParser.SourceClass doProcessConfigurationClass(ConfigurationClass configClass, ConfigurationClassParser.SourceClass sourceClass) throws IOException {
// 1. 處理內部類, 由於內部類的處理方式仍是跟這個方法一直的,因此咱們先忽略不看
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
this.processMemberClasses(configClass, sourceClass);
}
// 2. 處理@PropertySource,暫時看不懂
Iterator var3 = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class, PropertySource.class).iterator();
AnnotationAttributes importResource;
while(var3.hasNext()) {
importResource = (AnnotationAttributes)var3.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");
}
}
//3. 處理@ComponentScan
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
Iterator var13 = componentScans.iterator();
while(var13.hasNext()) {
// 3.1 獲取該配置類@componentScan註解的信息,包裝成一個map,AnnotationAttributes繼承的就是map,
詳細信息如圖1.9 所示
// AnnotationAttributes是繼承一個map,裏面存放了@ComponentScan註解裏面的值。
// 關於AnnotationMetadata 的詳細內容,後面再進行講解.
AnnotationAttributes componentScan = (AnnotationAttributes)var13.next();
// 3.2 交給ComponentScanParser 去解析 ,下面詳細講 parse(),大概的過程就是,獲取@ComponentScan註解掃描的路徑上的類,組裝成BeanDefinitionHolder.
// 此時scannedBeanDefinitions大概有
Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
Iterator var7 = scannedBeanDefinitions.iterator();
while(var7.hasNext()) {
BeanDefinitionHolder holder = (BeanDefinitionHolder)var7.next();
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
//繼續循環掃描,這個過程比較難理解
//就是經過1個配置類,而後發散去找到他們 @ComponentScan註解的類。
this.parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
this.processImports(configClass, sourceClass, this.getImports(sourceClass), true);
importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
String[] var19 = resources;
int var21 = resources.length;
for(int var22 = 0; var22 < var21; ++var22) {
String resource = var19[var22];
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
Set<MethodMetadata> beanMethods = this.retrieveBeanMethodMetadata(sourceClass);
Iterator var17 = beanMethods.iterator();
while(var17.hasNext()) {
MethodMetadata methodMetadata = (MethodMetadata)var17.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);
// 返回父類的SourceClass,
return sourceClass.getSuperClass();
}
}
// 沒有父類,則執行結束。
return null;
}
}
複製代碼
圖1.8:
圖1.9
交給ComponentScanParser
class ComponentScanAnnotationParser {
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry, componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
boolean useInheritedGenerator = BeanNameGenerator.class == generatorClass;
scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator : (BeanNameGenerator)BeanUtils.instantiateClass(generatorClass));
ScopedProxyMode scopedProxyMode = (ScopedProxyMode)componentScan.getEnum("scopedProxy");
if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
scanner.setScopedProxyMode(scopedProxyMode);
} else {
Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
scanner.setScopeMetadataResolver((ScopeMetadataResolver)BeanUtils.instantiateClass(resolverClass));
}
scanner.setResourcePattern(componentScan.getString("resourcePattern"));
AnnotationAttributes[] var15 = componentScan.getAnnotationArray("includeFilters");
int var8 = var15.length;
int var9;
AnnotationAttributes filter;
Iterator var11;
TypeFilter typeFilter;
for(var9 = 0; var9 < var8; ++var9) {
filter = var15[var9];
var11 = this.typeFiltersFor(filter).iterator();
while(var11.hasNext()) {
typeFilter = (TypeFilter)var11.next();
scanner.addIncludeFilter(typeFilter);
}
}
var15 = componentScan.getAnnotationArray("excludeFilters");
var8 = var15.length;
for(var9 = 0; var9 < var8; ++var9) {
filter = var15[var9];
var11 = this.typeFiltersFor(filter).iterator();
while(var11.hasNext()) {
typeFilter = (TypeFilter)var11.next();
scanner.addExcludeFilter(typeFilter);
}
}
boolean lazyInit = componentScan.getBoolean("lazyInit");
if (lazyInit) {
scanner.getBeanDefinitionDefaults().setLazyInit(true);
}
Set<String> basePackages = new LinkedHashSet();
String[] basePackagesArray = componentScan.getStringArray("basePackages");
String[] var19 = basePackagesArray;
int var21 = basePackagesArray.length;
int var22;
for(var22 = 0; var22 < var21; ++var22) {
String pkg = var19[var22];
String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg), ",; \t\n");
Collections.addAll(basePackages, tokenized);
}
Class[] var20 = componentScan.getClassArray("basePackageClasses");
var21 = var20.length;
for(var22 = 0; var22 < var21; ++var22) {
Class<?> clazz = var20[var22];
basePackages.add(ClassUtils.getPackageName(clazz));
}
if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(declaringClass));
}
scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
protected boolean matchClassName(String className) {
return declaringClass.equals(className);
}
});
// 這是真正的解析方法,這裏的
// basePackages = "**.**.**" //通常是 @ComponentScan(basePackages = "**")
// 掃描這個路徑下面全部的包以及包下面的內容
return scanner.doScan(StringUtils.toStringArray(basePackages));
}
}
// 掃描這個路徑下面全部的包以及包下面的內容
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet();
String[] var3 = basePackages;
int var4 = basePackages.length;
for(int var5 = 0; var5 < var4; ++var5) {
String basePackage = var3[var5];
// 這個方法是最重點,把掃描到的Bean就放進來了(好比此處只有RootConfig一個Bean定義,是個配置類)
// 3.2.1 這個是重點,會把該包下面全部的Bean都掃描進去。Spring5和一下的處理方式不同哦~
// 下面有講解
Set<BeanDefinition> candidates = this.findCandidateComponents(basePackage);
Iterator var8 = candidates.iterator();
// 開始遍歷掃描到得全部的類
while(var8.hasNext()) {
BeanDefinition candidate = (BeanDefinition)var8.next();
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
// 設置其 scope, 單例仍是多例
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
// // 此處爲掃描的Bean,爲ScannedGenericBeanDefinition,因此確定爲true
// 所以進來,執行postProcessBeanDefinition(對Bean定義信息作) 以下詳解
// 注意:只是添加些默認的Bean定義信息,並非執行後置處理器~~~
// 3.2.2
if (candidate instanceof AbstractBeanDefinition) {
this.postProcessBeanDefinition((AbstractBeanDefinition)candidate, beanName);
}
// 顯然,此處也是true 也是完善好比Bean上的一些註解信息:好比@Lazy、@Primary、@DependsOn、@Role、@Description 大概的操做方式是
abd.setDependsOn(dependsOn.getStringArray("value"));
@Role註解用於Bean的分類分組,沒有太大的做用
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition)candidate);
}
// 檢查這個Bean 好比
//若是dao包(通常配置的basePakage是這個)下的類是符合mybaits要求的則向spring IOC容器中註冊它的BeanDefinition 因此這步檢查第三方Bean的時候有必要檢查一下
if (this.checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
//AnnotationConfigUtils類的applyScopedProxyMode方法根據註解Bean定義類中配置的做用域@Scope註解的值,爲Bean定義應用相應的代理模式,主要是在Spring面向切面編程(AOP)中使用
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
// 在GenericApplicationContext中執行this.aliasMap.put(alias, name);
// this.beanDefinitionMap.put(beanName, beanDefinition)
// 在這裏把類BeanDefinitionHolder加載進 容器中的
this.registerBeanDefinition(definitionHolder, this.registry);
}
}
}
//
return beanDefinitions;
}
// 3.2.1 解析 掃描 RootConfig
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
// 上面說過了CandidateComponentsIndex是Spring5提供的優化掃描的功能
// 顯然這裏編譯器咱們沒有寫META-INF/spring.components索引文件,因此此處不會執行Spring5 的掃描方式,因此我暫時不看了(超大型項目纔會使用Spring5的方式)
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
} else {
// Spring 5以前的方式(絕大多數狀況下,都是此方式)
return scanCandidateComponents(basePackage);
}
}
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
LinkedHashSet candidates = new LinkedHashSet();
// classpath*:com/macro/mall/**/*.class
// resourcePatter是 **/*.class
// componentScan中就有指定了resourcePatter的內容是 "**/*.class"
try {
String packageSearchPath = "classpath*:" + this.resolveBasePackage(basePackage) + '/' + this.resourcePattern;
//getResourcePatternResolver獲取獲得的是 PathMatchingResourcePatternResolver
// 10.1.1 進行講解
Resource[] resources = this.getResourcePatternResolver().getResources(packageSearchPath);
// 記錄日誌(下面我把打印日誌地方都刪除)
boolean traceEnabled = this.logger.isTraceEnabled();
boolean debugEnabled = this.logger.isDebugEnabled();
Resource[] var7 = resources;
int var8 = resources.length;
// 接下來的這個for循環:就是把一個個的resource組裝成ScannedGenericBeanDefinition
for(int var9 = 0; var9 < var8; ++var9) {
Resource resource = var7[var9];
//文件必須可讀 不然直接返回空了
if (traceEnabled) {
this.logger.trace("Scanning " + resource);
}
// 要是可讀的
if (resource.isReadable()) {
try {
MetadataReader metadataReader = this.getMetadataReaderFactory().getMetadataReader(resource);
//// 根據TypeFilter過濾排除組件。由於AppConfig沒有標準@Component或者子註解,因此確定不屬於候選組件 返回false
// 注意:這裏通常(默認處理的狀況下)標註了默認註解的纔會true,什麼叫默認註解呢?就是@Component或者派生註解。還有javax....的,這裏省略啦
if (this.isCandidateComponent(metadataReader)) {
//
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
if (this.isCandidateComponent((AnnotatedBeanDefinition)sbd)) {
if (debugEnabled) {
this.logger.debug("Identified candidate component class: " + resource);
}
candidates.add(sbd);
} else if (debugEnabled) {
this.logger.debug("Ignored because not a concrete top-level class: " + resource);
}
} else if (traceEnabled) {
this.logger.trace("Ignored because not matching any filter: " + resource);
}
} catch (Throwable var13) {
throw new BeanDefinitionStoreException("Failed to read candidate component class: " + resource, var13);
}
} else if (traceEnabled) {
this.logger.trace("Ignored because not readable: " + resource);
}
}
return candidates;
} catch (IOException var14) {
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", var14);
}
}
//10.1.1 講解, 獲取掃描路徑下全部 ** 的類
public class PathMatchingResourcePatternResolver implements ResourcePatternResolver {
// 好比此時locationPattern是 "classpath: com/**/**/**/*.class"
protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {
// 此時的rootDirPath 是 com/**/**/
String rootDirPath = this.determineRootDir(
);
// 此時的subPattern是 **/*.class
String subPattern = locationPattern.substring(rootDirPath.length());
// 這個方法在下面 10.1.1.1 解析
// 獲得的結果是 URLResource,裏面是 URL url + String name
// 這裏獲得的URL內容是: file:/D:/project/mall/mall-admin/target/classes/com/macro/mall/], target裏面的內容
Resource[] rootDirResources = this.getResources(rootDirPath);
Set<Resource> result = new LinkedHashSet(16);
Resource[] var6 = rootDirResources;
int var7 = rootDirResources.length;
for(int var8 = 0; var8 < var7; ++var8) {
Resource rootDirResource = var6[var8];
Resource rootDirResource = this.resolveRootDirResource(rootDirResource);
URL rootDirUrl = ((Resource)rootDirResource).getURL();
if (equinoxResolveMethod != null && rootDirUrl.getProtocol().startsWith("bundle")) {
URL resolvedUrl = (URL)ReflectionUtils.invokeMethod(equinoxResolveMethod, (Object)null, new Object[]{rootDirUrl});
if (resolvedUrl != null) {
rootDirUrl = resolvedUrl;
}
rootDirResource = new UrlResource(rootDirUrl);
}
if (rootDirUrl.getProtocol().startsWith("vfs")) {
result.addAll(PathMatchingResourcePatternResolver.VfsResourceMatchingDelegate.findMatchingResources(rootDirUrl, subPattern, this.getPathMatcher()));
} else if (!ResourceUtils.isJarURL(rootDirUrl) && !this.isJarResource((Resource)rootDirResource)) {
//doFindPathMatchingFileResources直接走這裏,由於是文件的資源,不是jar包等,此時的 subPattern是「 **/*.class 」,因此邏輯是,獲得掃描rootDirResource,全部匹配subPattern(**/*.class)的類
result.addAll(this.doFindPathMatchingFileResources((Resource)rootDirResource, subPattern));
} else {
result.addAll(this.doFindPathMatchingJarResources((Resource)rootDirResource, rootDirUrl, subPattern));
}
}
if (logger.isTraceEnabled()) {
logger.trace("Resolved location pattern [" + locationPattern + "] to resources " + result);
}
return (Resource[])result.toArray(new Resource[0]);
}
// 10.1.1.1 根據基路徑 ,掃描其下全部資源
public Resource[] getResources(String locationPattern) throws IOException {
Assert.notNull(locationPattern, "Location pattern must not be null");
if (locationPattern.startsWith("classpath*:")) {
return
//直接看這一步findPathMatchingResources()
this.getPathMatcher().isPattern(locationPattern.substring("classpath*:".length())) ? this.findPathMatchingResources(locationPattern) : this.findAllClassPathResources(locationPattern.substring("classpath*:".length()));
} else {
int prefixEnd = locationPattern.startsWith("war:") ? locationPattern.indexOf("*/") + 1 : locationPattern.indexOf(58) + 1;
return this.getPathMatcher().isPattern(locationPattern.substring(prefixEnd)) ? this.findPathMatchingResources(locationPattern) : new Resource[]{this.getResourceLoader().getResource(locationPattern)};
}
}
//location 是 "/com/**/**"
protected Resource[] findAllClassPathResources(String location) throws IOException {
String path = location;
if (location.startsWith("/")) {
path = location.substring(1);
}
//直接看這裏
Set<Resource> result = this.doFindAllClassPathResources(path);
if (logger.isTraceEnabled()) {
logger.trace("Resolved classpath location [" + location + "] to resources " + result);
}
return (Resource[])result.toArray(new Resource[0]);
}
// 獲得的結果是URLResource [file:/D:/project/mall/mall-admin/target/classes/com/macro/mall/]
protected Set<Resource> doFindAllClassPathResources(String path) throws IOException {
Set<Resource> result = new LinkedHashSet(16);
ClassLoader cl = this.getClassLoader();
Enumeration resourceUrls = cl != null ? cl.getResources(path) : ClassLoader.getSystemResources(path);
while(resourceUrls.hasMoreElements()) {
URL url = (URL)resourceUrls.nextElement();
result.add(this.convertClassLoaderURL(url));
}
if ("".equals(path)) {
this.addAllClassLoaderJarRoots(cl, result);
}
return result;
}
}
複製代碼
從目錄中能夠看到,
仍是繼續講解refresh()的剩餘內容