SpringIOC 初始化过程–Bean容器的创建过程(基于AnnotationConfigApplicationContext方式)

Spring 最重要的概念是 IOC 和 AOP,在IOC中最重要的有两处,一个是创建Bean容器, 一个是初始化Bean,本章就是基于spring5.0.x讲述使用AnnotationConfigApplicationContext来讲解创建Bean容器;后面文章继续初始化Bean讲解;阅读Spring源码是一个枯燥的过程,愿君坚持下去;文章最后福利;福不福利的其实不重要,真的希望能坚持下去;

引言

前面构建了Spring的源码,在源码中我们写一个启动Spring容器的例子

IndexDao

public interface IndexDao {

String testSource();
}

IndexDaoImpl

@Service
public class IndexDaoImpl implements IndexDao {

public IndexDaoImpl() {
System.out.println("constructor");
}

public String testSource(){

return "test \n test2";
}
}

AppConfig

@Configuration
@ComponentScan("cn.haoxy")
public class AppConfig {
}

TestBean

public class TestBean {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AppConfig.class);
applicationContext.refresh();
IndexDao bean = applicationContext.getBean(IndexDao.class);
System.out.println(bean.testSource());
applicationContext.close();
}
}

build.gradle中引入spring-context

dependencies {
compile(project(":spring-context"))
testCompile group: 'junit', name: 'junit', version: '4.12'
}

类似我们在Maven构建项目时引入的

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.11.RELEASE</version>
</dependency>

在看关于spring源码的文章时很多都是基于 ClassPathXmlApplicationContext(...) 现在都基于springboot项目很少再使用xml的方式去配置,现在很多都是基于注解的方式; 所以本文我们使用AnnotationConfigApplicationContext();来进行讲解;

当然,除了这两个以外我们也还有其他构建 ApplicationContext 的方案可供选择:

image.png

FileSystemXmlApplicationContext: 的构造函数需要一个 xml 配置文件在系统中的路径,其他和 ClassPathXmlApplicationContext 基本上一样。

对于上面的类我们先混个眼熟就行;后面我们会再说到的;

启动过程分析

AnnotationConfigApplicationContext();方法介绍

第一步: 我们肯定要从AnnotationConfigApplicationContext的构造方法开始说起;

AnnotationConfigApplicationContext有父类,故先要执行父类的构造方法;父类的构造方法实例化一个工厂DefaultListableBeanFactory

public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}

到这里我们再来看一个类图:主要是BeanFactory介绍:

image.png
  • ApplicationContext 继承了 ListableBeanFactory,这个 Listable 的意思就是,通过这个接口,我们可以获取多个 Bean,大家看源码会发现,最顶层 BeanFactory 接口的方法都是获取单个 Bean 的。

  • ApplicationContext 继承了 HierarchicalBeanFactory,Hierarchical 单词本身已经能说明问题了,也就是说我们可以在应用中起多个 BeanFactory,然后可以将各个 BeanFactory 设置为父子关系。

  • AutowireCapableBeanFactory 这个名字中的 Autowire 大家都非常熟悉,它就是用来自动装配 Bean 用的,但是仔细看上图,ApplicationContext 并没有继承它,不过不用担心,不使用继承,不代表不可以使用组合,如果你看到 ApplicationContext 接口定义中的最后一个方法 getAutowireCapableBeanFactory() 就知道了。

  • ConfigurableListableBeanFactory 也是一个特殊的接口,看图,特殊之处在于它继承了第二层所有的三个接口,而 ApplicationContext 没有。这点之后会用到。

  • 然后,请读者打开编辑器,翻一下 BeanFactory、ListableBeanFactory、HierarchicalBeanFactory、AutowireCapableBeanFactory、ApplicationContext 这几个接口的代码,

  • 下面我们着重介绍一下DefaultListableBeanFactory,我们可以看到 ConfigurableListableBeanFactory 只有一个实现类 DefaultListableBeanFactory,而且实现类 DefaultListableBeanFactory 还通过实现右边的 AbstractAutowireCapableBeanFactory 通吃了右路。所以结论就是,最底下这个家伙 DefaultListableBeanFactory 基本上是最牛的 BeanFactory 了,这也是为什么这边会使用这个类来实例化的原因。上面在的构造方法中实例化了DefaultListableBeanFactory,DefaultListableBeanFactory类中定义了

    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);private volatile List<String> beanDefinitionNames = new ArrayList<>(256);至于这两个东西是做什么的,我们需要先了解一下BeanDefinition;

BeanDefinition介绍

我们来看下 BeanDefinition 的接口定义:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

// 我们可以看到,默认只提供 sington 和 prototype 两种,
// 很多读者可能知道还有 request, session, globalSession, application, websocket 这几种,
// 不过,它们属于基于 web 的扩展。
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

// 比较不重要,直接跳过吧
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;

// 设置父 Bean,这里涉及到 bean 继承,不是 java 继承。请参见附录的详细介绍
// 一句话就是:继承父 Bean 的配置信息而已
void setParentName(String parentName);

// 获取父 Bean
String getParentName();

// 设置 Bean 的类名称,将来是要通过反射来生成实例的
void setBeanClassName(String beanClassName);

// 获取 Bean 的类名称
String getBeanClassName();


// 设置 bean 的 scope
void setScope(String scope);

String getScope();

// 设置是否懒加载
void setLazyInit(boolean lazyInit);

boolean isLazyInit();

// 设置该 Bean 依赖的所有的 Bean,注意,这里的依赖不是指属性依赖(如 @Autowire 标记的),
// 是 depends-on="" 属性设置的值。
void setDependsOn(String... dependsOn);

// 返回该 Bean 的所有依赖
String[] getDependsOn();

// 设置该 Bean 是否可以注入到其他 Bean 中,只对根据类型注入有效,
// 如果根据名称注入,即使这边设置了 false,也是可以的
void setAutowireCandidate(boolean autowireCandidate);

// 该 Bean 是否可以注入到其他 Bean 中
boolean isAutowireCandidate();

// 主要的。同一接口的多个实现,如果不指定名字的话,Spring 会优先选择设置 primary 为 true 的 bean
void setPrimary(boolean primary);

// 是否是 primary 的
boolean isPrimary();

// 如果该 Bean 采用工厂方法生成,指定工厂名称;
// 一句话就是:有些实例不是用反射生成的,而是用工厂模式生成的
void setFactoryBeanName(String factoryBeanName);
// 获取工厂名称
String getFactoryBeanName();
// 指定工厂类中的 工厂方法名称
void setFactoryMethodName(String factoryMethodName);
// 获取工厂类中的 工厂方法名称
String getFactoryMethodName();

// 构造器参数
ConstructorArgumentValues getConstructorArgumentValues();

// Bean 中的属性值,后面给 bean 注入属性值的时候会说到
MutablePropertyValues getPropertyValues();

// 是否 singleton
boolean isSingleton();

// 是否 prototype
boolean isPrototype();

// 如果这个 Bean 是被设置为 abstract,那么不能实例化,
// 常用于作为 父bean 用于继承,其实也很少用......
boolean isAbstract();

int getRole();
String getDescription();
String getResourceDescription();
BeanDefinition getOriginatingBeanDefinition();
}

在Java中,一切皆对象。在JDK中使用java.lang.Class来描述这个对象。

在Spring中,存在bean这样一个概念,那Spring又是怎么抽象bean这个概念,用什么类来描述bean这个对象呢?Spring使用BeanDefinition来描述bean

BeanDefinition有很多子类例如:

image.png

我们继续往下看

public AnnotationConfigApplicationContext() {
/**
* 创建一个读取注解的Bean定义读取器
*/
this.reader = new AnnotatedBeanDefinitionReader(this);


//可以用来扫描包或者类,继而转换成BeanDefinition
//但是实际上我们扫描包工作不是scanner这个对象来完成的而是
//spring自己new的一个ClassPathBeanDefinitionScanner
//这里的scanner仅仅是为了程序员能够在外部调用AnnotationConfigApplicationContext对象的scan方法
this.scanner = new ClassPathBeanDefinitionScanner(this);
}

上面代码首先在AnnotationConfigApplicationContext构造方法中实例化了一个读取器和扫描器;重点看上面的注释;

紧接着看下AnnotatedBeanDefinitionReader(this);里面做了什么事情

org.springframework.context.annotation.AnnotatedBeanDefinitionReader#AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment)

org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source)

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {

DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
//AnnotationAwareOrderComparator主要能解析@Order注解和@Priority
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
//ContextAnnotationAutowireCandidateResolver提供处理延迟加载的功能
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}

Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
//BeanDefinitio的注册,这里很重要,需要理解注册每个bean的类型
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//需要注意的是ConfigurationClassPostProcessor的类型是BeanDefinitionRegistryPostProcessor
//而 BeanDefinitionRegistryPostProcessor 最终实现BeanFactoryPostProcessor这个接口
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source)
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}

if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//AutowiredAnnotationBeanPostProcessor 实现了 MergedBeanDefinitionPostProcessor
//MergedBeanDefinitionPostProcessor 最终实现了 BeanPostProcessor
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}

if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}

//省略
........

return beanDefs;
}

上面代码主要做了以下几件事:

  • 拿到上面在父类构造方法中实例化的一个工厂DefaultListableBeanFactory

  • DefaultListableBeanFactory工厂中添加AnnotationAwareOrderComparator主要解析@Order注解和@Priority处理优先级;

  • DefaultListableBeanFactory工厂中添加ContextAnnotationAutowireCandidateResolver提供处理延迟加载的功能

  • 注册spring内部自己定义的bean;并放入到beanDefinitionMapbeanDefinitionNames中,这里着重看一下

    org.springframework.context.annotation.internalConfigurationAnnotationProcessor=ConfigurationClassPostProcessor这里有个印象后面会再次说到;

    例如:

image.png

这个方法到这里就结束了,这就是 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();所做的事情;

register()方法介绍

我们接着看下面applicationContext.register(AppConfig.class);

public void register(Class<?>... annotatedClasses) {
for (Class<?> annotatedClass : annotatedClasses) {
registerBean(annotatedClass);
}
}
public void registerBean(Class<?> annotatedClass) {
doRegisterBean(annotatedClass, null, null, null);
}
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
/**
* 根据指定的bean创建一个BeanDefinition的子类AnnotatedGenericBeanDefinition
* 这个AnnotatedGenericBeanDefinition可以理解为一个数据结构
* AnnotatedGenericBeanDefinition包含了类的其他信息,比如一些元信息
* scope,lazy等等
*
*/

AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
/**
* 判断这个类是否需要跳过解析
* 通过代码可以知道spring判断是否跳过解析,主要判断类有没有加注解
*/
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}

abd.setInstanceSupplier(instanceSupplier);
/**
* 得到类的作用域
*/
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
/**
* 把类的作用域添加到数据结构结构中
*/
abd.setScope(scopeMetadata.getScopeName());
/**
* 生成类的名字通过beanNameGenerator
*/
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
/**
* 处理类当中的通用注解
* 分析源码可以知道他主要处理
* Lazy DependsOn Primary Role等等注解
* 处理完成之后processCommonDefinitionAnnotations中依然是把他添加到数据结构当中
*
*/
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

/**
* 如果传参中带了这些注解类就会为true, 否则qualifiers一直为空
* 因为这里传如的是null(doRegisterBean(annotatedClass, null, null, null);)
*/
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
////如果配置了@Primary注解,如果加了则作为首选
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
//懒加载
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
//如果使用了除@Primary和@Lazy以外的其他注解,则为该Bean添加一个根据名字自动装配的限定符
//这里难以理解,后面会详细介绍
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
//这里也为null
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
customizer.customize(abd);
}

/**
* 这个BeanDefinitionHolder也是一个数据结构
*/
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);

/**
* ScopedProxyMode 跳过
*/
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

/**
* 把上述的这个数据结构注册给registry
* registry就是AnnotationConfigApplicationContext
* AnnotationConfigApplicationContext在初始化的時候通過調用父類的構造方法
* 实例化了一个DefaultListableBeanFactory
* registerBeanDefinition里面就是把definitionHolder这个数据结构包含的信息注册到
* DefaultListableBeanFactory这个工厂
*/
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

总结一下这个方法所做的事情:

  • 根据指定的bean创建一个BeanDefinition的子类AnnotatedGenericBeanDefinition

  • 得到当前类的作用域,当前传入的是AppConfig.class(默认是singleton);把类的作用域添加到AnnotatedGenericBeanDefinition中

  • 生成bean的名字并放入BeanDefinitionHolder中

  • 处理当前类使用的通用注解,详细看代码上的注释

  • 实例化一个BeanDefinitionHolder,相当于一个中间媒介;来存放BeanDefinition和beanName然后注册给registry,这里的registry就是AnnotationConfigApplicationContext,在AnnotationConfigApplicationContext的父类中实例化了一个DefaultListableBeanFactory;DefaultListableBeanFactory 中有个Map集合
    private final Map<String, BeanDefinition> bdMap = new ConcurrentHashMap<>(256);
    就是在这个方法中将AppConfig.class放入到beanDefinitionMap 中的;那现在beanDefinitionMap 的size大小就是7个;到
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);方法中看下;最终走了
    org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition方法中的

    else {
    // Still in startup registration phase
    this.beanDefinitionMap.put(beanName, beanDefinition);
    this.beanDefinitionNames.add(beanName);
    this.manualSingletonNames.remove(beanName);
    }

    applicationContext.register(AppConfig.class);方法到这里也就结束了;

下面我们进入今天的重要部分:

refresh()方法

org.springframework.context.support.AbstractApplicationContext#refresh

@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
//准备工作包括设置启动时间,是否激活标识位,
// 初始化属性源(property source)配置
prepareRefresh();

// Tell the subclass to refresh the internal bean factory.
//返回一个factory 为什么需要返回一个工厂
//因为要对工厂进行初始化
/** 这里说明一下:如果你使用是的xml配置的方式就会执行 AbstractRefreshableApplicationContext的refreshBeanFactory方法去加载xml配置信息;因为ClassPathXmlApplicationContext是它的子类;现在我们使用的是注解配置的方式所以会执行GenericApplicationContext的refreshBeanFactory方法,这个方法就是只返回了一个beanFactory**/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Prepare the bean factory for use in this context.
//准备工厂
prepareBeanFactory(beanFactory);

try {
// Allows post-processing of the bean factory in context subclasses.

//这个方法在当前版本的spring是没用任何代码的
//可能spring期待在后面的版本中去扩展吧
postProcessBeanFactory(beanFactory);

// Invoke factory processors registered as beans in the context.
//在spring的环境中去执行已经被注册的 factory processors
//设置执行自定义的ProcessBeanFactory 和spring内部自己定义的
invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.
//注册beanPostProcessor
registerBeanPostProcessors(beanFactory);

// Initialize message source for this context.
// 初始化当前 ApplicationContext 的 MessageSource,国际化这里就不展开说了
initMessageSource();

// Initialize event multicaster for this context.
//初始化应用事件广播器
initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.
// 从方法名就可以知道,典型的模板方法(钩子方法),
// 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
onRefresh();

// Check for listener beans and register them.
// 注册事件监听器,监听器需要实现 ApplicationListener 接口。这也不是我们的重点,过
registerListeners();

// Instantiate all remaining (non-lazy-init) singletons.
// 重点,重点,重点
// 初始化所有的 singleton beans
//(lazy-init 的除外)
finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.
// 最后,广播事件,ApplicationContext 初始化完成
finishRefresh();
}
//.......

prepareRefresh();,obtainFreshBeanFactory();都没有什么好说的看上面的注释就可以,这里我们简单介绍一下prepareBeanFactory(beanFactory);方法;

prepareBeanFactory()

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 设置 BeanFactory 的类加载器,我们知道 BeanFactory 需要加载类,也就需要类加载器,
// 这里设置为加载当前 ApplicationContext 类的类加载器
beanFactory.setBeanClassLoader(getClassLoader());
//bean表达式解释器, 为了能够让我们的beanFactory去解析bean表达式
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//对象与string类型的转换 <property red="dao">
//想深入了解参考 https://blog.csdn.net/pentiumchen/article/details/44026575
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

//添加一个后置管理器ApplicationContextAwareProcessor
// 能够在bean中获得到各种*Aware(*Aware都有其作用)
// 这个我们很常用,如我们会为了获取 ApplicationContext 而 implement ApplicationContextAware
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 下面几行的意思就是,如果某个 bean 依赖于以下几个接口的实现类,在自动装配的时候忽略它们,
// Spring 会通过其他方式来处理这些依赖。
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

// 下面几行就是为特殊的几个 bean 赋值,如果有 bean 依赖了以下几个,会注入这边相应的值,
//MessageSource 被注册成为了一个普通的 bean
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);

// 这个 BeanPostProcessor 也很简单,在 bean 实例化后,如果是 ApplicationListener 的子类,
// 那么将其添加到 listener 列表中,可以理解成:注册 事件监听器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

// 这里涉及到特殊的 bean,名为:loadTimeWeaver,这不是我们的重点,忽略它
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}

//意思是如果自定义的Bean中没有名为"systemProperties"和"systemEnvironment"的Bean,
// 则注册两个Bena,Key为"systemProperties"和"systemEnvironment",Value为Map,
// 这两个Bean就是一些系统配置和系统环境信息
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}

上面prepareBeanFactory方法只是给beanFactory增加一些特殊的东西例如:表达式解析器,后置处理器,忽略一些特定的类;至此beanFactory中的beanDefinitionMap 的size大小依然还是7个;

postProcessBeanFactory(beanFactory);是一个空方法;

下面重点介绍一下invokeBeanFactoryPostProcessors(beanFactory);

invokeBeanFactoryPostProcessors()

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
//这里的getBeanFactoryPostProcessors()是获取手动给spring的BeanFactoryPostProcessors()
//何为手动给spring --> 手动调用AnnotationConfigApplicationContext.addBeanFactoryPostProcessor();
//所以说自定义的BeanFactoryPostProcessors并非只有implements BeanFactoryPostProcessors才叫自定义
//我们并没有手动去调用所以getBeanFactoryPostProcessors()的size = 0

//这里问: 那如果我们自己去implements BeanFactoryPostProcessors 那getBeanFactoryPostProcessors()的size还会不会是0?
//回答: 还是0! 因为我们自己implements BeanFactoryPostProcessors必须要加@Component,但是直到现在为止spring并没有开始扫描@Component
//所以还是0
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}

进入invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());方法

下面的信息量比较大,我们先看一下下面代码中需要的类图,先熟悉一下,有助于理解;

image.png
public static void invokeBeanFactoryPostProcessors(
//List<BeanFactoryPostProcessor> beanFactoryPostProcessors 这个是我们手动传过来的
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
//这里肯定是会进的,当前的beanFactory 一直都是 DefaultListableBeanFactory,而DefaultListableBeanFactory是BeanDefinitionRegistry的子类
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
//BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor
//BeanDefinitionRegistryPostProcessor功能比BeanFactoryPostProcessor更强大
//我们自己要是想扩展有两种方式;1:实现BeanFactoryPostProcessor,2,BeanDefinitionRegistryPostProcessor,所以定义了两个来存放,
//这里之所以实例化两个list的目的是:进行区分,spring对这两个有不同的处理方式

List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<>();
//这里是size=0;上面的代码注释中解释过
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
//如我们自己implements BeanDefinitionRegistryPostProcessor并且没有加@Component而是我们自己手动添加的ApplicationContext.addBeanFactoryPostProcessor(new TestBeanDefinitionRegistryPostProcessor());那么在下面这句话就会执行重写的方法;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
} else {
regularPostProcessors.add(postProcessor);
}
}
//这里又定义了一个,和上面的区别是,这个currentRegistryProcessors 放的是spring内部自己实现了BeanDefinitionRegistryPostProcessor接口的对象
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
//BeanDefinitionRegistryPostProcessor 等于 BeanFactoryPostProcessor
//getBeanNamesForType 根据bean的类型获取bean的名字 ConfigurationClassPostProcessor
//这里的getBeanNamesForType代码就不展开了大致说下 就是拿到beanDefinitionNames中的7个值去对和BeanDefinitionRegistryPostProcessor对比看是否是他的子类
//这里7个中只有一个ConfigurationClassPostProcessor是它的子类,所以值取到了一个ConfigurationClassPostProcessor
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
//ConfigurationClassPostProcessor我们在最开始介绍注册spring内部自己定义的bean时,向beanDefinitionMap添加了6个(AppConfig.calss之外)中,其中一个就是它;
//这里解释一下为什么要在最开始注册这个呢?因为spring的工厂需要去解析,扫描等等功能
//而这些功能都是需要在spring工厂初始化完成之前执行
//要么在工厂最开始的时候、要么在工厂初始化之中,反正不能再之后
//因为如果在之后就没有意义,因为那个时候已经需要使用工厂了
//所以这里Spring在一开始就注册了一个BeanFactoryPostProcessor,用来插手SpringFactory的实例化过程
//而这个类叫做ConfigurationClassPostProcessor
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//添加到集合currentRegistryProcessors中
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
//添加到processedBeans的Set集合中
processedBeans.add(ppName);
}
}
//排序不重要,况且currentRegistryProcessors这里也只有一个数据
sortPostProcessors(currentRegistryProcessors, beanFactory);
//合并list,不重要(为什么要合并,因为有我们自定义个还有spring自己内部实现的)
registryProcessors.addAll(currentRegistryProcessors);

/**
* //最重要。注意这里是方法调用
* //调用这个方法
* //循环所有的BeanDefinitionRegistryPostProcessor
* //该方法内部postProcessor.postProcessBeanDefinitionRegistry
*/
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
//这个list只是一个临时变量,故而要清除
currentRegistryProcessors.clear();
// 下面的代码先不看,等invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);执行完之后我们回头再看....
}

这里就不总结了,看上面的代码注释就很清楚了,下面

invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);是重点,我们进去看看做了什么事?

private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

//只有一条数据
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}

然后执行了
org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
之后执行了
org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions 我们着重看下这个方法!

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
//定义一个list 存放 applicationContext 提供的bd
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
//获取容器中注册的所有bd名字 这里会有7个
String[] candidateNames = registry.getBeanDefinitionNames();

/**
* Full : 加了Configuration注解的类会被Sping标记为Full
* Lite : 其他注解标记为Lite
*/
//遍历beanName 拿出的所有bd(BeanDefinition),然后判断bd时候包含了@Configuration、@Import,@Compent。。。注解
//这里循环7,但是有个6个我们都不需要看,我们只看AppConfig
for (String beanName : candidateNames) {
//根据bean名称得到具体的BeanDefinition
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
//检查是否被处理过
//如果BeanDefinition中的configurationClass属性为full或者lite,则意味着已经处理过了,直接跳过
//进去下面checkConfigurationClassCandidate方法就会明白这句话的意思
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
//判断是否是Configuration类,如果加了Configuration注解下面的这几个注解就不再判断了
/**
* candidateIndicators.add(Component.class.getName());
* candidateIndicators.add(ComponentScan.class.getName());
* candidateIndicators.add(Import.class.getName());
* candidateIndicators.add(ImportResource.class.getName());
*/
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
//BeanDefinitionHolder 也可以看成一个数据结构,将BeanDefinitionHolder添加到上面实例化的一个configCandidates集合中;
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}

// Return immediately if no @Configuration classes were found
if (configCandidates.isEmpty()) {
return;
}

// 排序,根据order,不重要
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});

//如果BeanDefinitionRegistry是SingletonBeanRegistry子类的话,
// 由于我们当前传入的是DefaultListableBeanFactory,是SingletonBeanRegistry 的子类
// 因此会将registry强转为SingletonBeanRegistry
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}

if (this.environment == null) {
this.environment = new StandardEnvironment();
}

// 实例化ConfigurationClassParser 为了解析各个配置类
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);

//实例化2个set,candidates用于将之前加入的configCandidates进行去重
//因为可能有多个配置类重复了
//alreadyParsed用于判断是否处理过
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
//扫描包,将去重后的candidates集合传入;里面只有一个appConfig
parser.parse(candidates);
parser.validate();

Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);

// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
/**
*
* 这里值得注意的是扫描出来的bean当中可能包含了特殊类
* 比如ImportBeanDefinitionRegistrar那么也在这个方法里面处理
* 但是并不是包含在configClasses当中
* configClasses当中主要包含的是importSelector
* 因为ImportBeanDefinitionRegistrar在扫描出来的时候已经被添加到一个list当中去了
*
*/
//bd 到 map
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);

candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
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());

// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}

if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}

这个方法有点长,而且很重要,需要慢慢看;在这个方法中我们只需要针对AppConfig这个类看就可以了其他6个可以跳过;

我们先进入一下checkConfigurationClassCandidate方法,看看是怎么检查注解又怎么标识Full和Lite的;

public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
String className = beanDef.getBeanClassName();
if (className == null || beanDef.getFactoryMethodName() != null) {
return false;
}

AnnotationMetadata metadata;
//......由于篇幅原因,省略一些代码,用一句话来说明一下;这个metadata是怎么来的
/**
1,如果BeanDefinition 是 AnnotatedBeanDefinition的实例,并且className 和 BeanDefinition中的元 数据的类名相同,则直接从BeanDefinition 获得Metadata
2,如果BeanDefinition 是 AbstractBeanDefinition的实例,并且beanDef 有 beanClass 属性存在
则实例化StandardAnnotationMetadata
**/


//判断当前这个bd中存在的类是不是加了@Configruation注解
//如果存在则spring认为他是一个全注解的类
if (isFullConfigurationCandidate(metadata)) {
//如果存在Configuration 注解,则为BeanDefinition 设置configurationClass属性为full
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
//判断是否加了以下注解,摘录isLiteConfigurationCandidate的源码
// candidateIndicators.add(Component.class.getName());
// candidateIndicators.add(ComponentScan.class.getName());
// candidateIndicators.add(Import.class.getName());
// candidateIndicators.add(ImportResource.class.getName());
//如果不存在Configuration注解,spring则认为是一个部分注解类
else if (isLiteConfigurationCandidate(metadata)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
return false;
}

// It's a full or lite configuration candidate... Let's determine the order value, if any.
Integer order = getOrder(metadata);
if (order != null) {
beanDef.setAttribute(ORDER_ATTRIBUTE, order);
}

return true;
}

isFullConfigurationCandidate();

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

isLiteConfigurationCandidate();

static {
candidateIndicators.add(Component.class.getName());
candidateIndicators.add(ComponentScan.class.getName());
candidateIndicators.add(Import.class.getName());
candidateIndicators.add(ImportResource.class.getName());
}

下面我们重点分析parse方法

public void parse(Set<BeanDefinitionHolder> configCandidates) {
this.deferredImportSelectors = new LinkedList<>();
//根据BeanDefinition 的类型 做不同的处理,一般都会调用ConfigurationClassParser#parse 进行解析
//遍历configCandidates中的BeanDefinitionHolder取出BeanDefinition
//BeanDefinition中包含了AppConfig的一些属性信息
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
//当前bd类型就是AnnotatedBeanDefinition --> true
if (bd instanceof AnnotatedBeanDefinition) {
//解析注解对象,并且把解析出来的bd放到map,但是这里的bd指的是普通的
//何谓不普通的呢?比如@Bean 和各种beanFactoryPostProcessor得到的bean不在这里put
//但是这里解析,只是put而已
//Metadata中主要包含的是解析出来的注解,当前AppConfig 解析出来的注解是@Configuration,@ComponentScan
//注解何时被解析出来的呢? 就是一开始将AppConfig 加载到BeanDefinitionMap中时;
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
//处理延迟加载的importSelect
processDeferredImportSelectors();
}

然后进入真正的解析方法:
org.springframework.context.annotation.ConfigurationClassParser#parse(AnnotationMetadata, String)
在这个方法中又调用了:
org.springframework.context.annotation.ConfigurationClassParser#processConfigurationClass方法;

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
// 处理Imported 的情况
//就是当前这个注解类有没有被别的类import
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
// Otherwise ignore new imported config class; existing non-imported class overrides it.
return;
}
else {
// Explicit bean definition found, probably replacing an imports.
// Let's remove the old one and go with the new one.
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
}

// 递归地处理配置类及其超类层次结构。
SourceClass sourceClass = asSourceClass(configClass);
do {
//解析注解并扫描
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
//一个map,用来存放扫描出来的bean(注意这里的bean不是对象,仅仅bean的信息,因为还没到实例化这一步)
this.configurationClasses.put(configClass, configClass);
}

然后进入doProcessConfigurationClass()方法,下面不重要的代码我就不贴了;

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {

//处理内部类 一般不会写内部类
processMemberClasses(configClass, sourceClass);

// 处理@PropertySource注释
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}

// 处理@ComponentScan注释
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
//解析扫描的一些基本信息,比如是否过滤,比如是否加入新的包。。。。。includeFilters,excludeFilters等等都是ComponentScan中的属性
//扫描普通类-->componentScan ---> com.haoxy
//这里扫描出来所有@Component
//并且把扫描的出来的普通bean放到map当中
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
//检查扫描出来的类当中是否还有@Configuration
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}

//下面是处理@Import imports 3种情况
//ImportSelector
//普通类
//ImportBeanDefinitionRegistrar
//这里和内部地柜调用时候的情况不同
/**
* 这里处理的import是需要判断我们的类当中时候有@Import注解
* 如果有这把@Import当中的值拿出来,是一个类
* 比如@Import(xxxxx.class),那么这里便把xxxxx传进去进行解析
* 在解析的过程中如果发觉是一个importSelector那么就回调selector的方法
* 返回一个字符串(类名),通过这个字符串得到一个类
* 继而在递归调用本方法来处理这个类
*
* 判断一组类是不是imports(3种import)
*
*代码就不贴了,不是咱们这次研究的重点
*/
processImports(configClass, sourceClass, getImports(sourceClass), true);
//..........
}

上面的代码就是扫描普通类—-@Component,包括@Component子类: @Repository @Controller @service;并且放到了BeanDefinitionMap当中;

进入org.springframework.context.annotation.ComponentScanAnnotationParser#parse方法;这里就是处理ComponentScan注解中的一些属性;例如scopedProxy,scopeResolver,includeFilters,excludeFilters,lazyInit,basePackages,basePackageClasses,等…我们直接进入parse方法的org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan方法;这个方法把@ComponentScan中的值传了过去;

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
//获取到包名
for (String basePackage : basePackages) {
//扫描basePackage路径下的java文件
//符合条件的并把它转成BeanDefinition类型
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
//解析scope属性
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
//生成bean名称
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
//如果这个类是AbstractBeanDefinition的子类
//则为他设置默认值,比如lazy,init destory
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
//检查并且处理常用的注解
//这里的处理主要是指把常用注解的值设置到AnnotatedBeanDefinition当中
//当前前提是这个类必须是AnnotatedBeanDefinition类型的,说白了就是加了注解的类
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
//根据包名扫描到的类加载到beanDefinition map 中
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}

扫描候选组件的类路径方法:
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#findCandidateComponents

public Set<BeanDefinition> findCandidateComponents(String basePackage) {
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
//根据索引获得bean定义,配合spring-context-indexer使用,有兴趣得自己去了解一下,这里不做具体得解析
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
}
else {
//扫描获得bean定义
return scanCandidateComponents(basePackage);
}
}
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
//classpath*:cn/haoxy/**/*.class ant path模式串
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
//这里resources有四个;分别是 TestBean.class,AppConfig.class,IndexDao.class,IndexDaoImpl.class
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
//遍历resources;
for (Resource resource : resources) {
if (traceEnabled) {
logger.trace("Scanning " + resource);
}
if (resource.isReadable()) {
try {
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
//判断是否是我们需要的资源
/**
* 通过isCandidateComponent(MetadataReader metadataReader)来根据excludeFilters和includeFilters判断是否可以进行下一步的操作,
* 如果这个资源被排除的filter匹配上,就返回false,代表不是我们所需要的。
* 如果被包含的filter匹配上,并且他还要通过条件判断isConditionMatch的话,返回true,代表是我们需要的资源,可以进行下一步的操作。
* 这里我们插一句Spring有默认的includ类型的filter实现,如果上层传入的话,就是用上层传入的,否则就使用默认的,
* 默认的是扫描@Component注解以及他的子类@Repository @Controller @service
*/
//显然这里只会匹配一个IndexDaoImpl.class
if (isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
}
candidates.add(sbd);
}
//........省

}
catch (IOException ex) {
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
}
return candidates;
}

这里只会有一个IndexDaoImpl符合我们的要求,放到candidates集合中并返回到doScan方法中;然后解析此类的作用域scope,生成bean名称等,然后调用registerBeanDefinition(definitionHolder, this.registry);方法把它加入到beanDefinitionMap集合中;

下面我们看看registerBeanDefinition(definitionHolder, this.registry)方法

org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerBeanDefinition
方法转来转去最后转到了
org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition方法;

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {

Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");

if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanNam)....
}
}
//所有的 Bean 注册后会放入这个 beanDefinitionMap 中
//判断beanDefinitionMap中是否存在当前bean;之所以判断是因为我们可以配置允许bean覆盖
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
//显然这里是不成立的,我们并没有配置允许bean覆盖,existingDefinition中也不会存在我们当前bean
if (existingDefinition != null) {
//如果进到这里说明我们允许了bean的覆盖
if (!isAllowBeanDefinitionOverriding()) {
// 如果不允许覆盖的话,抛异常
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName)....
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
//这里的代码都是打印日志 log....
//日志内容: 用框架定义的 Bean 覆盖用户自定义的 Bean
//.....
else if (!beanDefinition.equals(existingDefinition)) {
//log....
//日志内容: 用新的 Bean 覆盖旧的 Bean
}
else {
//log....
//日志内容: 用同等的 Bean 覆盖旧的 Bean,这里指的是 equals 方法返回 true 的 Bean
}
//覆盖bean
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
//上面的if不成立就来到了这里;如果是普通bean(IndexDaoImpl等),这里返回是true,
// 如果是AppConfig等特殊bean,Spring一开始就加载的会走下面的else
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
//以beanName为key,beanDefinition为value put 到 beanDefinitionMap中;
//注意,"注册Bean" 这个动作结束,Bean 依然还没有初始化,我们后面会有大篇幅说初始化过程,
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
//将beanName 添加到 beanDefinitionNames集合中
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
//特殊bean
else {
// Still in startup registration phase
//同样是以beanName为key,beanDefinition为value put 到 beanDefinitionMap中;
this.beanDefinitionMap.put(beanName, beanDefinition);
//将beanName 添加到 beanDefinitionNames集合中
this.beanDefinitionNames.add(beanName);
//这LinkedHashSet存放的是:environment,systemProperties,systemEnvironment
//都是一些系统环境,系统属性,这里对我们不重要
this.manualSingletonNames.remove(beanName);
}
// 这个不重要,在预初始化的时候会用到,不必管它。
this.frozenBeanDefinitionNames = null;
}

if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}

这时候beanDefinitionMap的size大小就是8个了;然后放到beanDefinitions集合中返回;这里只是把它加入到beanDefinitionMap集合中还没有进行初始化;上面就是@ComponentScan注解作用的扫描BeanDefination的全部过程了。这一篇文章终于结束了,好累,自己总结了一遍印象更深刻一些;下一篇文章开始bean的创建过程以及初始化;

福利:带中文注释的Spring源码