打个广告
个人想写《springboot源码解析》这一系列很久了,但是一直角儿心底的知识积累不足,所以一直没有动笔。
所以想找一些小伙伴一起写这一系列,互相纠错交流学习。
如果有小伙伴有兴趣一起把这一系列的讲解写完的话,加下我微信:13670426148,我们一起完成,当交流学习。
后期还想写一系列介绍rpc框架的,不过要再过一阵子了,先把springboot的写完
前言
直接讲了 refresh()
的代码实现,直到完成配置类的实例化为止,后面的registerBeanPostProcessors
方法还没开始讲。
refresh总方法
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();
}
}
}
1. prepareRefresh()刷新容器前的准备
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 :
2. 创建新的beanFactory
两步,第一步创建新的beanFactory,第二步是进行基本的配置
1.创建新的beanFacotry,实际创建的为DefaultListableBeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//在application中创建DefaultListableBeanFactory并赋值给上下文中的this.beanFactory,相当于原先那个不要了,创建一个新的.
this.refreshBeanFactory();
return this.getBeanFactory();
}
其中refreshBeanFactory()方法是通过 GenericApplicationContext
来执行的这个
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());
}
}
}
2. 配置beanFactory
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:
而 DefaultListableBeanFactory
中存在的是
beanDefinitionMap
和 resolvableDependencies
和 beanDefinitionNames
和 manualSingletonNames
beanDefinitionNames
记录了创建了的beanDefinition的类型集合,beanDefinitionMap存放的是beanDefinition映射。迄今为止已经存在的有:
图1.3
而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
- DefaultSingletonBeanRegistry是在实例化bean的时候用到的,实例化好的单例类信息都存放在其中
- DefaultListableBeanFactory 是在xml扫描或者注解扫描类时候组装BeanDefinition的过程用到的类
- AbstractBeanFactory是配置工厂基本配置信息,比如BeanPostProcessor类,或者注册解析器PropertyEditor等时候用到
不得不说“单一职责原则”在这里体现的挺充分的,每个类都有各自的意义。
3. 注册后置处理器BeanPostProcessor
添加一个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个了.
4. 执行 Bean工厂后置处理器BeanFactoryPostProcessor
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
中的。
交给PostProcessorRegistrationDelegate处理
//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:
1. bean定义有关的BeanDefinitionRegistryPostProcessor的执行
里面总共有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()));
}
}
}
2. 执行 ConfigurationClassPostPorcessor
//此时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();
}
}
}
}
1.2 判断其是否是配置类
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;
}
}
}
1.3. parse开始解析,交给ConfigurationClassParser
//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
3.2 ComponentScanParser 解析扫描路径
交给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), ",;
");
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;
}
}
总结
从目录中可以看到,
- (1) 一开始是设置配置环境、监听器等
- (2)之后是创建DefaultListableBeanFactory
-(3)接下来是执行beanFactoryPostProcessor,其中涉及到创建配置类的过程,交给了ConfigurationClassParser和ClassPathBeanDefinitionScanner去扫描循环解析。
下期预告
还是继续讲解refresh()的剩余内容