spring篇:IOC容器加载过程源码探究(二)

本节继续上节文章,上节文章说到第三步实例化AnnotatedBeanDefinitionReader完毕,接下来说第四步:
4.实例化扫描器:ClassPathBeanDefinitionScanner
这里的扫描器仅仅是提供给开发者手动调用的,即AnnotationConfigApplicationContext对象.scan()方法。
5.注册bean配置类为BeanDefinition:register(annotatedClasses);

	public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
		//调用构造函数
		this();
		//注册我们的配置类
		register(annotatedClasses);
		//IOC容器刷新接口
		refresh();
	}

进入register(annotatedClasses)方法:

	public void register(Class<?>... annotatedClasses) {
		Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
		this.reader.register(annotatedClasses);
	}

进入this.reader.register(annotatedClasses)方法:

	public void register(Class<?>... annotatedClasses) {
		for (Class<?> annotatedClass : annotatedClasses) {
			registerBean(annotatedClass);
		}
	}

进入registerBean(annotatedClass)方法:

	public void registerBean(Class<?> annotatedClass) {
		doRegisterBean(annotatedClass, null, null, null);
	}

进入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) {
		//转为AnnotatedGenericBeanDefinition数据结构,里面有一个getMetadata方法,可以拿到类上的注解
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
	   //验证是否跳过注解,当不满足条件时,就会跳过
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}

		abd.setInstanceSupplier(instanceSupplier);
	    //解析bean的作用域,如果没有设置的话,默认为单例
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		abd.setScope(scopeMetadata.getScopeName());
		//得到beanName
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
		//解析通用注解,填充到AnnotatedGenericBeanDefinition,解析的注解为Lazy,Primary,DependsOn,Role,Descri ption
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
		//限定符处理,不是特指@Qualifier注解,也有可能是Primary,或者是Lazy,或者是其他(理论上是任何注解)
		qualifiers永远都是空的,包括上面的name和instanceSupplier都是同样的道理 
		//但是spring提供了其他方式去注册bean,就可能会传入了
		if (qualifiers != null) {
			for (Class<? extends Annotation> qualifier : qualifiers) {
				if (Primary.class == qualifier) {
					abd.setPrimary(true);
				}
				else if (Lazy.class == qualifier) {
					abd.setLazyInit(true);
				}
				else {
					abd.addQualifier(new AutowireCandidateQualifier(qualifier));
				}
			}
		}
		for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
			customizer.customize(abd);
		}
		//把AnnotatedGenericBeanDefinition数据结构和beanName封装到一个对象中
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		//注册,最终会调用DefaultListableBeanFactory中的registerBeanDefinition方法去注册;
		//DefaultListableBeanFactory维护着一系列信息,比如beanDefinitionNames,
		//beanDefinitionMap  beanDefinitionNames是一个List<String>,用来保存beanName ;
		//beanDefinitionMap是一个Map,用来保存beanName和beanDefinition。
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}

说明:
1.常规的方式注册配置类,除了第一个参数,其他参数都是默认值。
2.通过AnnotatedGenericBeanDefinition的构造方法,获得配置类的BeanDefinition,这和之前在注册ConfigurationClassPostProcessor类的时,也是通过构造方法去获得 BeanDefinition的,只不过当时是通过RootBeanDefinition去获得,现在是通过 AnnotatedGenericBeanDefinition去获得。
3.判断需不需要跳过注册,Spring中有一个@Condition注解,如果不满足条件,就会跳过这个类的 注册。
4.获得BeanName
5.解析通用注解,填充到AnnotatedGenericBeanDefinition,解析的注解为Lazy,Primary, DependsOn,Role,Description。
6. 限定符处理,不是特指@Qualifier注解,也有可能是Primary,或者是Lazy,或者是其他
7. 把AnnotatedGenericBeanDefinition数据结构和beanName封装到一个对象中(方便传参)
8. 最终会调用DefaultListableBeanFactory中的registerBeanDefinition方法去注册:

	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		//获取bean
		String beanName = definitionHolder.getBeanName();
		//注册bean定义
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		//注册bean名称的别名
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}
	}

至此,配置类注册完毕。

6.非常重要的一个方法 refresh():

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
		//调用构造函数
		this();
		//注册我们的配置类
		register(annotatedClasses);
		//IOC容器刷新接口
		refresh();
	}

进入refresh()方法:

	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			//1:准备刷新上下文环境
			prepareRefresh();

			//2:获取告诉子类初始化Bean工厂
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			//3:对bean工厂进行填充属性
			prepareBeanFactory(beanFactory);

			try {
				// 第四:留个子类去实现该接口
				postProcessBeanFactory(beanFactory);

				// 调用我们的bean工厂的后置处理器.
				invokeBeanFactoryPostProcessors(beanFactory);

				// 调用我们bean的后置处理器
				registerBeanPostProcessors(beanFactory);

				// 初始化国际化资源处理器.
				initMessageSource();

				// 创建事件多播器
				initApplicationEventMulticaster();

				// 这个方法同样也是留个子类实现的springboot也是从这个方法进行启动tomat的.
				onRefresh();

				//把我们的事件监听器注册到多播器上
				registerListeners();

				//实例化我们剩余的单实例bean.
				finishBeanFactoryInitialization(beanFactory);

				// 最后容器刷新 发布刷新事件(Spring cloud也是从这里启动的)
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception  encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

说明:
①prepareRefresh():刷新前准备工作,保存了容器的启动时间,启动标志等。
②ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory():把beanFactory取出来,XML模式下会在这里读取BeanDefinition。
③prepareBeanFactory():准备工作,为bean工厂添加了两个后置处理器,ApplicationContextAwareProcessor,ApplicationListenerDetector,还设置了忽略自动装配和允许自动装配的接口,如果不存在某个bean的时候,spring就自动注册singleton bean,还设置了bean表达式解析器等。进入prepareBeanFactory()方法,一探究竟:

	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		//设置bean工厂的类加载器为当前application应用的加载器
		beanFactory.setBeanClassLoader(getClassLoader());
		//为bean工厂设置我们标准的SPEL表达式解析器对象StandardBeanExpressionResolver
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		//为我们的bean工厂设置了一个propertityEditor 属性资源编辑器对象(用于后面的给bean对象赋值使用)
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		//注册了一个完整的ApplicationContextAwareProcessor 后置处理器用来处理ApplicationContextAware接口的回调方法
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));


		/**
		 * 当 Spring 将 Applie础onContextAwareProcessor 注册后,那么在 invokeAwarelnterfaces 方法中间接调用的 Aware 类已经不是普通的 bean 了 ,
		 * 如 ResourceLoaderAware、 ApplicationEventPublisher 等,那么当然需要在 Spring 做 bean 的依赖注入的时候忽略它们。
		 * 而 ignoreDependencyInterface 的作用正是在此
		 */
		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.class 的解析依赖后,
		 * 当 bean 的属性注入的时候, 一旦检测到属性为 BeanFactory 类型便会将 beanFactory 的实例注入进去。
		 */
		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));

		// 处理aspectj的
		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工厂的内部的bean
		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());
		}
	}

说明:该方法主要做了如下操作:
① 设置了一个类加载器
②设置了bean表达式解析器
③ 添加了属性编辑器的支持
④添加了一个后置处理器:ApplicationContextAwareProcessor,此后置处理器实现了BeanPostProcessor接口
⑤设置了一些忽略自动装配的接口
⑥ 设置了一些允许自动装配的接口,并且进行了赋值操作
⑦在容器中还没有XX的bean的时候,帮我们注册beanName为XX的singleton bean

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值