Spring源码(二)SpringIOC初始化过程源码分析-基于注解方式

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

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

若是以为观看时候来回拉滚动条不方便请使用我的博客观看git

引言

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

IndexDaogithub

public interface IndexDao {

	String testSource();
}
复制代码

IndexDaoImplweb

@Service
public class IndexDaoImpl implements IndexDao {

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

	public String testSource(){

		return "test \n test2";
	}
}
复制代码

AppConfigspring

@Configuration
@ComponentScan("cn.haoxy")
public class AppConfig {
}
复制代码

TestBeanspringboot

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-contextwebsocket

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

相似咱们在Maven构建项目时引入的session

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.0.11.RELEASE</version>
</dependency>
复制代码

在看关于spring源码的文章时不少都是基于ApplicationContext context = new ClassPathXmlApplicationContext(...)如今都基于springboot项目不多再使用xml的方式去配置,如今不少都是基于注解的方式;因此本文咱们使用AnnotationConfigApplicationContext applicationContext = new 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> beanDefinitionMap = new ConcurrentHashMap<>(256);就是在这个方法中将AppConfig.class放入到beanDefinitionMap 中的;那如今beanDefinitionMap 的size大小就是7个;能够debbug到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源码, 博客总结

使用博客观看效果更佳

相关文章
相关标签/搜索