spring5.0 源码解析(day01) BeanFactory 和 ApplicationContext

Ioc 容器的设计

在这里插入图片描述

  • BeanFactory:接口定义了基本的IoC容器规范,包括 getBean()这样的ioc容器的基本方法

  • HierarchicalBeanFactory: (Hierarchical (分层的))接口在继承BeanFactory接口之后,增加个 getParentBeanFactory() 方法,使BeanFactory具备了双亲 IoC容器的管理功能

  • ConfigurableBeanFactory:主要定义了beanFactory 的配置功能,setParentBeanFactory()设置双亲Ioc容器, addBeanPostProcessor() 配置bean的后置处理器等等

  • ListableBeanFactory: 细化了BeanFactory的接口功能,getBeanDefinitionNames()返回工厂中所有bean名称,

  • MessageSource:一个消息的策略接口,以用于支持信息的国际化和包含参数的信息的替换。(策略模式)

  • ApplicationEventPublisher:封装事件发布的接口(观察者模式)

  • ResourceLoader: 支持资源加载的策略接口

  • EnvironmentCapable: 提供了getEnvironment()方法 返回 表示当前应用程序运行的环境

  • ApplicationContext : 他实现了 EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, 具有了一个Ioc容器的基本能力, 同时实现了MessageSource, ApplicationEventPublisher, ResourcePatternResolver具有了更高级的Ioc 容器的特性

BeanFactory 的应用

BeanFactory 提供了最基本的 IOC 容器的功能,也制定了 IOC 容器所应遵守的最底层和最基本的编程规范

BeanFactory 使负责管理bean的,FanctoryBean是一个能产生或者修饰对象生成的工厂bean,我的理解他的存在是为了可以通过代码的实现来生成复杂的bean对象,通过 FanctoryBean 的beanName 获取到的 bean 是工厂bean生产出的bean,通过 & + FanctoryBean 的beanName 来获取工厂bean本身

BeanFactory相关方法

方法描述
Object getBean(String name) throws BeansException通过 beanName 获取bean
boolean containsBean(String name)判断容器中是否存在指定名称的bean
boolean isSingleton(String name)判断bean 的scope 是否为 Singleton
boolean isPrototype(String name)判断bean 的scope 是否为 Prototype
boolean isTypeMatch(String name, ResolvableType typeToMatch)检查具有给定名称的 bean 是否与指定类型匹配
Class<?> getType(String name) throws NoSuchBeanDefinitionException;获取bean 的class类型
String[] getAliases(String name);获取 bean的所有别名

这些方法…代表最基本的容器入口

ApplicationContext

ApplicationContext 是一个更高级意义上的IoC容器

  • 继承 EnvironmentCapable 可以获取程序运行环境
  • 继承 ListableBeanFactory, HierarchicalBeanFactory 具有了容器的基本功能
  • 继承 MessageSource 支持信息的国际化
  • 继承 ApplicationEventPublisher 支持事件发布
  • 继承 ResourceLoader 可以从不同位置加载bean定义资源

Ioc 容器的初始化过程

IoC容器的初始化是通过 refresh() 方法来启动的,这个启动包括了BeanDefinition的Resource定位、载入、注册三个过程。

  1. resouce 资源定位: 它是由ResourceLoader通过统一的Resource接口来实现的
    在这里插入图片描述
    在文件系统中的bean可以使用FileSystemResourceLoader来进行抽象,在类路径下bean可以使用ClassPathContextResource 来抽象,这个过程就是容器在寻找数据的过程

  2. 第二个过程是BeanDefination的载入,这个过程就是把用户定义好的bean表示成IoC容器的内部的数据结构

    • BeanDefination 实际上是bean在Ioc容器中的抽象,
  3. 第三个过程想IoC容器中注入这些BeanDefination的过程,这个过程是通过调用 BeanDefinitionRegistry 接口的实现来完成的,通俗来讲就是将 BeanDefination 保存(注册)到Ioc容器当中

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
	/** bean 定义对象的映射,以 bean 名称为键. */
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
}

refreshBeanFactory()

refresh调用 refreshBeanFactory ,在这个方法中 通过 createBeanFactory() 构件了一个ioc 容器 供 ApplicationContext
使用,这个 容器 就是 DefaultListableBeanFactory , 之后 通过 loadBeanDefinitions(beanFactory); 来载入 BeanDifination,

// 创建一个ioc 容器
protected DefaultListableBeanFactory createBeanFactory() {
		return new DefaultListableBeanFactory(getInternalParentBeanFactory());
	}
		// 存在bean工厂 销毁bean工厂
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		// 创建并设置持有的 DefaultListableBeanFactory 的地方同时调用
		try {
			// 创建bean工厂
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			// 指定序列化 ID
			beanFactory.setSerializationId(getId());
			// 设置 beanFactoty 细节
			 //  1. 是否允许bean定义覆盖
			 //  2. 是否允许循环引用
			customizeBeanFactory(beanFactory);

			// 加载 beanDeanDefinitions
			loadBeanDefinitions(beanFactory);
			// 设置 beanFactory 持有
			this.beanFactory = beanFactory;
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}

loadBeanDefinitions

这里我们以 AnnotationConfigWebApplicationContext 基于去讲解 其实这里 loadBeanDefinitions() 的不同实现就是为了 在不同的配置中加载 BeanDefinitions,最终目标还是将 BeanDefinitions注册到容器中

第一步初始化 BeanDefinitionReader 和 DefinitionScanner

		// AnnotatedBeanDefinitionReade读取器用来加载class类型的配置
		AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory);
		// ClassPathBeanDefinitionScanner是一个扫描指定类路径中注解Bean定义的扫描器
		ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory);

第二步设置 BeanNameGenerator

// 设置 beanName 生成器    BeanNameGenerator 是一个策略接口用于为给定的 bean 定义生成一个 bean 名称
		BeanNameGenerator beanNameGenerator = getBeanNameGenerator();
		if (beanNameGenerator != null) {
			reader.setBeanNameGenerator(beanNameGenerator);
			scanner.setBeanNameGenerator(beanNameGenerator);
			beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
		}

第三步 设置 ScopeMetadataResolver

//  ScopeMetadataResolver 用于解析bean定义范围的策略接口 
		ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver();
		if (scopeMetadataResolver != null) {
			reader.setScopeMetadataResolver(scopeMetadataResolver);
			scanner.setScopeMetadataResolver(scopeMetadataResolver);
		}

第四步bean 注册

		// 使用 reader 注册bean 配合传入的配置类
	  	if (!this.componentClasses.isEmpty()) {
			if (logger.isDebugEnabled()) {
				logger.debug("Registering component classes: [" +
						StringUtils.collectionToCommaDelimitedString(this.componentClasses) + "]");
			}
			reader.register(ClassUtils.toClassArray(this.componentClasses));
		}
		// 使用 scan注册bean 配合传入的配置类
		if (!this.basePackages.isEmpty()) {
			if (logger.isDebugEnabled()) {
				logger.debug("Scanning base packages: [" +
						StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]");
			}
			scanner.scan(StringUtils.toStringArray(this.basePackages));
		}
		// 用于 xml 配置 这种本地配置的bean 的注册
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			for (String configLocation : configLocations) {
				try {
					Class<?> clazz = ClassUtils.forName(configLocation, getClassLoader());
					if (logger.isTraceEnabled()) {
						logger.trace("Registering [" + configLocation + "]");
					}
					reader.register(clazz);
				}
				catch (ClassNotFoundException ex) {
					if (logger.isTraceEnabled()) {
						logger.trace("Could not load class for config location [" + configLocation +
								"] - trying package scan. " + ex);
					}
					int count = scanner.scan(configLocation);
					if (count == 0 && logger.isDebugEnabled()) {
						logger.debug("No component classes found for specified class/package [" + configLocation + "]");
					}
				}
			}
		}

beanDefination 的 register

registerBean 调用 doRegisterBean

		// 给创建的bean 创建BeanDefinition 并且解析了注解数据
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}
	
		abd.setInstanceSupplier(supplier);
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		abd.setScope(scopeMetadata.getScopeName());  // 设置bean的作用域
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));  				  			  //       生成beanName 
		// 扫描bean 的注解设置相关注解信息 这里已经根据bean上的注解设置了一次属性
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

		// 根据Qualifier注解 强制更改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));
				}
			}
		}
		if (customizers != null) {
			for (BeanDefinitionCustomizer customizer : customizers) {
				customizer.customize(abd);
			}
		}
		// 带有名称和别名的 BeanDefinition 的持有者。可以注册为内部 bean 的占位符
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);

		// 判断是否为 代理对象bean 定义以那种模式生成代理对象
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		// 注册到 beanDefinitionRegister
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1999

每人一点点,明天会更好

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值