Spring的一些源码分析part.1(bean生命周期准备部分)

阶段一:
  1. MyTest.java(测试类)
// 测试类mian()函数中
ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);  <— — — — — — 1.进入

解释:这里我们使用AnnotationConfigApplicationContext来进行测试,它需要传入一个@Configuration的java配置类。

  1. AnnotationConfigApplicationContext
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
	// 调用无参构造方法,但是首先要调用其父类的无参构造方法
	this();   <— — — — — — 2.查看其父类
	register(componentClasses);   
	refresh();
	}
public class AnnotationConfigApplicationContext extends
				GenericApplicationContext implements AnnotationConfigRegistry {    <— — — — — — 3.查看其父类

解释:我们可以看到AnnotationConfigApplicationContext的直接父类是GenericApplicationContext,同时它还实现了AnnotationConfigRegistry接口。

  1. GenericApplicationContext
// 直接父类
public class GenericApplicationContext extends 
				AbstractApplicationContext implements BeanDefinitionRegistry {    <— — — — — — 4.查看其父类

解释:GenericApplicationContext的直接父类是AbstractApplicationContext,同时它还是一个BeanDefinitionRegistry。
⚠️重点:BeanDefinitionRegistry相当于BeanDefinition的数据库,是装载bean信息的仓库,等会儿有大用处。
所以GenericApplicationContext身兼两职。

  1. AbstractApplicationContext
// 直接父类
public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {

解释:AbstractApplicationContext的直接父类是一个DefaultResourceLoader。
⚠️重点:DefaultResourceLoader是整个Spring容器负责加载资源(配置文件)的加载器,等会儿有大用处。
AbstractApplicationContext也是一个ConfigurableApplicationContext,这才是它的主业。所以AbstractApplicationContext也是身兼两职。

  1. DefaultResourceLoader
// 直接父类
// DefaultResourceLoader是一个ResourceLoader
public class DefaultResourceLoader implements ResourceLoader {

找父类终于到头了,我们来看看它的无参构造方法。

public DefaultResourceLoader() {
	this.classLoader = ClassUtils.getDefaultClassLoader();   <— — — — — — 5.进入
	}
  1. ClassUtils
@Nullable
public static ClassLoader getDefaultClassLoader() {
	ClassLoader cl = null;
	try {
		// 得到调用线程的类加载器, 也就是一个AppClassLoader
		cl = Thread.currentThread().getContextClassLoader();
	}
	catch (Throwable ex) {
	// Cannot access thread context ClassLoader - falling back...
	}
	if (cl == null) {
		// No thread context class loader -> use class loader of this class.
		cl = ClassUtils.class.getClassLoader();
		if (cl == null) {
			// getClassLoader() returning null indicates the bootstrap ClassLoader
			try {
				cl = ClassLoader.getSystemClassLoader();
			}
			catch (Throwable ex) {
				// Cannot access system ClassLoader - oh well, maybe the caller can live with null...
			}
		}
	}
	// 返回类加载器AppClassLoader,一路返回
	return cl;     <— — — — — — 6.返回
}

返回DefaultResourceLoader无参构造方法
返回AbstractApplicationContext无参构造方法

  1. AbstractApplicationContext
// AbstractApplicationContext无参构造方法
public AbstractApplicationContext() {
	this.resourcePatternResolver = getResourcePatternResolver();   <— — — — — — 7.进入
	}
  1. AbstractApplicationContext
protected ResourcePatternResolver getResourcePatternResolver() {
	// new一个PathMatchingResourcePatternResolver,
	// 传入本AbstractApplicationContext对象
	return new PathMatchingResourcePatternResolver(this);  <— — — — — — 8.进入
	}
  1. PathMatchingResourcePatternResolver
public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {
	Assert.notNull(resourceLoader, "ResourceLoader must not be null");
	// 赋给PathMatchingResourcePatternResolver的resourceLoader成员为本AbstractApplicationContext对象
	// ⚠️刚刚讲过本AbstractApplicationContext就是一个ResourceLoader、资源加载器
	this.resourceLoader = resourceLoader;
	}

补充可以看到:PathMatchingResourcePatternResolver是一个ResourcePatternResolver

public class PathMatchingResourcePatternResolver 
		implements ResourcePatternResolver {

那么ResourcePatternResolver是什么呢?在Spring容器中扮演什么角色呢?其实ResourcePatternResolver是一个接口,它扩展了ResourceLoader接口,如图
在这里插入图片描述
第8步~10步总结:其实就是AbstractApplicationContext在它的无参构造方法中,给自己的resourcePatternResolver成员变量,赋了PathMatchingResourcePatternResolver实例。

好,继续返回

  1. GenericApplicationContext
// 重点⚠️
public GenericApplicationContext() {
	// 赋给beanFactory成员变量一个DefaultListableBeanFactory()
	// 这里不进入了,到此为止
	// 就理解为,我们现在得到了一个DefaultListableBeanFactory实例对象
	this.beanFactory = new DefaultListableBeanFactory();  
	}

总结:我们到现在为止现在获得了什么?

  • 一个DefaultListableBeanFactory实例对象,它是一个BeanFactory
  • 一个PathMatchingResourcePatternResolver实例对象,它是一个ResourceLoader
  • 一个该线程对象的classLoader实例对象

简单说明:

  • BeanFactory是我们Spring容器最核心的部分,主要指责是实例化bean,初始化bean
  • ResourceLoader是我们Spring容器专门去加载配置文件的工具,比如xml、 @Configuration配置类等

这些组件等会都有用。

现在继续返回,最终回到了我们的AnnotationConfigApplicationContext无参构造方法


阶段二:

阶段二主要是去获取一个AnnotatedBeanDefinitionReader和一个ClassPathBeanDefinitionScanner。

  1. AnnotationConfigApplicationContext
public AnnotationConfigApplicationContext() {
	// 初始化reader属性,new一个AnnotatedBeanDefinitionReader, 传入本AnnotationConfigApplicationContext对象
	this.reader = new AnnotatedBeanDefinitionReader(this);   <— — — — — — 9.进入
	this.scanner = new ClassPathBeanDefinitionScanner(this);
	}
  1. AnnotatedBeanDefinitionReader
// 参数registry就是我们的AnnotationConfigApplicationContext
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
	this(registry, getOrCreateEnvironment(registry));   <— — — — — — 10.进入getOrCreateEnvironment
	}

解释:由于刚刚说了,AnnotationConfigApplicationContext继承了GenericApplicationContext,而GenericApplicationContext是一个BeanDefinitionRegistry。所以AnnotationConfigApplicationContext是一个BeanDefinitionRegistry

那么AnnotatedBeanDefinitionReader是什么呢?
在这里插入图片描述

  1. AnnotatedBeanDefinitionReader
// 参数registry就是我们的AnnotationConfigApplicationContext
private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
	Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
	// 进入if
	if (registry instanceof EnvironmentCapable) {
		return ((EnvironmentCapable) registry).getEnvironment();   <— — — — — — 10.进入
		}
	return new StandardEnvironment();
	}

为什么会进入if?
解释:因为AnnotationConfigApplicationContext最终实现了ApplicationContext接口,而ApplicationContext继承了EnvironmentCapable接口。

  1. AbstractApplicationContext
// 该方法由AbstractApplicationContext实现
@Override
public ConfigurableEnvironment getEnvironment() {
	if (this.environment == null) {
		this.environment = createEnvironment();  <— — — — — — 11.进入
	}
	return this.environment;
}
  1. AbstractApplicationContext
protected ConfigurableEnvironment createEnvironment() {
	return new StandardEnvironment();  <— — — — — — 12.返回
	}

解释:暂时没有搞懂StandardEnvironment是干什么的。

  1. AnnotatedBeanDefinitionReader
// 回到AnnotatedBeanDefinitionReader构造方法
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
	this(registry, getOrCreateEnvironment(registry));   <— — — — — — 11.进入this
	}
  1. AnnotatedBeanDefinitionReader
// AnnotatedBeanDefinitionReader构造方法
// 参数registry是我们的AnnotationConfigApplicationContext
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
	Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
	Assert.notNull(environment, "Environment must not be null");
	// 初始化成员变量registry
	this.registry = registry;
	// 下面这句意义不明,暂时不看
	this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
	// 下面这句估计是注册所有注解后置处理器,不看
	// ⚠️后来补充:是的,注册了几个工厂后处理器的bean的BeanDefinition
	AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
	// 返回
	}

总结:这句代码大概就是实例化了一个AnnotatedBeanDefinitionReader,它是可以从注解配置资源中读取bean信息的reader工具。

this.reader = new AnnotatedBeanDefinitionReader(this);

在这里插入图片描述

  1. AnnotationConfigApplicationContext
public AnnotationConfigApplicationContext() {
	this.reader = new AnnotatedBeanDefinitionReader(this);
	// 初始化scanner对象
	// 由于里面比较冗杂,不太想去读,跳过
	// 大概就是进行各种设置
	this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

至此,AnnotationConfigApplicationContext的无参构造方法调用完成
12步~19步略显意义不明

总结
阶段二我们得到了什么呢?

  • AnnotatedBeanDefinitionReader
  • ClassPathBeanDefinitionScanner

简单说明:AnnotatedBeanDefinitionReader的作用在于解析ResourceLoader读取进来的Resource,Resource里面包含了配置文件里的所有bean信息,包括(bean实现类、bean的id、bean依赖、bean作用域等信息)


补充:其实此时Spring容器已经偷偷地在DefaultListableBeanFactory的beanDefinitionMap的注册了几个Spring内置默认的bean的BeanDefinition了。就在第18步的⚠️位置(当时不想进去分析了)。
在这里插入图片描述
所以此时我们的“bean数据库”——BeanDefinitionRegistry已经不是空空的了,已经有几个bean的BeanDefinition在里面了。


阶段三(注册Java配置类的BeanDefinition)
  1. AnnotationConfigApplicationContext
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
	this();   
	// 注册我们传过来的@Configuration的Java配置类的class
	register(componentClasses);    <— — — — — — 12.进入
	refresh();
	}
  1. AnnotationConfigApplicationContext
public void register(Class<?>... componentClasses) {
	Assert.notEmpty(componentClasses, "At least one component class must be specified");
	this.reader.register(componentClasses);   <— — — — — — 13.进入
	}
  1. AnnotatedBeanDefinitionReader
public void register(Class<?>... componentClasses) {
	// 遍历传入的@Configuration的Java配置类的class,有可能有多个Java类
	for (Class<?> componentClass : componentClasses) {
		// 注册这些Java配置类
		registerBean(componentClass);    <— — — — — — 14.进入
	}
}
  1. AnnotatedBeanDefinitionReader
public void registerBean(Class<?> beanClass) {
	doRegisterBean(beanClass, null, null, null, null);  <— — — — — — 15.进入
	}
  1. AnnotatedBeanDefinitionReader
// ⚠️这里比较核心,就是把bean的信息变成BeanDefinition的过程
// ⚠️这里还实现了把BeanDefinition注册进BeanDefinitionRegistry的过程
// 但是比较复杂,就简单说说
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
		@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
		@Nullable BeanDefinitionCustomizer[] customizers) {

	// new一个AnnotatedGenericBeanDefinition,包裹Java配置类
	// 这里应该完成了BeanDefinition的创建和转换
	AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
	if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
		return;
	}

	// 对AnnotatedGenericBeanDefinition进行一些设置
	abd.setInstanceSupplier(supplier);
	// 得到该bean的作用域元信息
	ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
	// 设置作用域
	abd.setScope(scopeMetadata.getScopeName());
	// 得到bean的名字
	String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

	// 根据qualifiers为BeanDefinition设置一些属性,懒加载之类的
	AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
	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);
		}
	}

	// 用一个definitionHolder来装载我们的BeanDefinition
	BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
	definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
	// ⚠️把BeanDefinition注册进BeanDefinitionRegistry
	BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);    
	// 结束返回
}

解释:最后一句,最终其实是把BeanDefinition最终放在了

  • DefaultListableBeanFactory的一个HashMap类型成员变量里,叫beanDefinitionMap。
  • DefaultListableBeanFactory也是一个BeanDefinitionRegistry,最终是DefaultListableBeanFactory来容纳这些BeanDefinition。
    在DefaultListableBeanFactory的
    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
    方法中,调用了下面这句
this.beanDefinitionMap.put(beanName, beanDefinition);
  • DefaultListableBeanFactory成员beanDefinitionMap:
/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

至此:

  1. 把Java配置类读入
  2. 把该Java配置类转换为beanDefinition
  3. 把beanDefinition注册进BeanDefinitionRegistry

总结:现在我们有了以下成果:

  • 有了BeanFactory实例
  • BeanDefinitionRegistry里面已经注册了Java配置类的BeanDefinition,和一些其他内置bean的BeanDefinition
  1. AnnotationConfigApplicationContext
// 又回到了这里
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
		this();  //✅
		register(componentClasses);   //✅
		refresh();   <— — — — — — 16.进入
	}

阶段四(refresh方法、工厂后处理器的使用)

refresh()是整个Bean生命周期最重要的方法,没有之一。它的整个方法体就代表了从BeanDefinition的加工到Bean的实例化、最后到Bean的实例化、最后把Bean放入缓存池的过程。

⚠️注意:

  • beanFactoryPostProcessors是ApplicationContext的一个成员变量
  • beanPostProcessors是beanFactory的一个成员变量
    (但是它们里面的元素不一定长期驻留)
  1. AbstractApplicationContext
    refresh()方法就包含了整个Bean的IoC创建的生命周期,所以非常重要。⚠️refresh()是整个Spring中最重要的方法。没有之一
@Override
public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// Prepare this context for refreshing.
		// 初始化属性源配置
		prepareRefresh();    
		
		// Tell the subclass to refresh the internal bean factory.
		// 就设置了一下序列化的版本号,返回刚刚第一、二阶段的DefaultListableBeanFactory实例
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// 为beanFactory设置在此应用中需要的各种组件:ClassLoader、ResourceLoader...
		// 这里beanFactory注册了一些bean后置处理器(此处不确定是不是全部都注册了),之前是没有的
		
		prepareBeanFactory(beanFactory);

		try {
			// 准备工厂(不太明白❔)
			postProcessBeanFactory(beanFactory);
			
			// 此时还没有所谓的“InstantiationStrategy”
			// 此时的beanDefinitionMap里只有一些内置的beanDefinition,和Java配置类beanDefinition
			// 此函数调用工厂后处理器
			invokeBeanFactoryPostProcessors(beanFactory);   < -----16.简单进入看看

			// 注册所有bean后置处理器
			registerBeanPostProcessors(beanFactory);

			initMessageSource();

			initApplicationEventMulticaster();

			onRefresh();

			registerListeners();

			finishBeanFactoryInitialization(beanFactory);

			finishRefresh();
		}

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

			destroyBeans();

			cancelRefresh(ex);

			throw ex;
		}

		finally {
			resetCommonCaches();
		}
	}
}

见pt2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值