阶段一:
- MyTest.java(测试类)
// 测试类mian()函数中
ApplicationContext context = new AnnotationConfigApplicationContext(Config.class); <— — — — — — 1.进入
解释:这里我们使用AnnotationConfigApplicationContext来进行测试,它需要传入一个@Configuration的java配置类。
- AnnotationConfigApplicationContext
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
// 调用无参构造方法,但是首先要调用其父类的无参构造方法
this(); <— — — — — — 2.查看其父类
register(componentClasses);
refresh();
}
public class AnnotationConfigApplicationContext extends
GenericApplicationContext implements AnnotationConfigRegistry { <— — — — — — 3.查看其父类
解释:我们可以看到AnnotationConfigApplicationContext的直接父类是GenericApplicationContext,同时它还实现了AnnotationConfigRegistry接口。
- GenericApplicationContext
// 直接父类
public class GenericApplicationContext extends
AbstractApplicationContext implements BeanDefinitionRegistry { <— — — — — — 4.查看其父类
解释:GenericApplicationContext的直接父类是AbstractApplicationContext,同时它还是一个BeanDefinitionRegistry。
⚠️重点:BeanDefinitionRegistry相当于BeanDefinition的数据库,是装载bean信息的仓库,等会儿有大用处。
所以GenericApplicationContext身兼两职。
- AbstractApplicationContext
// 直接父类
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
解释:AbstractApplicationContext的直接父类是一个DefaultResourceLoader。
⚠️重点:DefaultResourceLoader是整个Spring容器负责加载资源(配置文件)的加载器,等会儿有大用处。
AbstractApplicationContext也是一个ConfigurableApplicationContext,这才是它的主业。所以AbstractApplicationContext也是身兼两职。
- DefaultResourceLoader
// 直接父类
// DefaultResourceLoader是一个ResourceLoader
public class DefaultResourceLoader implements ResourceLoader {
找父类终于到头了,我们来看看它的无参构造方法。
public DefaultResourceLoader() {
this.classLoader = ClassUtils.getDefaultClassLoader(); <— — — — — — 5.进入
}
- 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无参构造方法
- AbstractApplicationContext
// AbstractApplicationContext无参构造方法
public AbstractApplicationContext() {
this.resourcePatternResolver = getResourcePatternResolver(); <— — — — — — 7.进入
}
- AbstractApplicationContext
protected ResourcePatternResolver getResourcePatternResolver() {
// new一个PathMatchingResourcePatternResolver,
// 传入本AbstractApplicationContext对象
return new PathMatchingResourcePatternResolver(this); <— — — — — — 8.进入
}
- 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实例。
好,继续返回
- 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。
- AnnotationConfigApplicationContext
public AnnotationConfigApplicationContext() {
// 初始化reader属性,new一个AnnotatedBeanDefinitionReader, 传入本AnnotationConfigApplicationContext对象
this.reader = new AnnotatedBeanDefinitionReader(this); <— — — — — — 9.进入
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
- AnnotatedBeanDefinitionReader
// 参数registry就是我们的AnnotationConfigApplicationContext
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry)); <— — — — — — 10.进入getOrCreateEnvironment
}
解释:由于刚刚说了,AnnotationConfigApplicationContext继承了GenericApplicationContext,而GenericApplicationContext是一个BeanDefinitionRegistry。所以AnnotationConfigApplicationContext是一个BeanDefinitionRegistry
那么AnnotatedBeanDefinitionReader是什么呢?
- 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接口。
- AbstractApplicationContext
// 该方法由AbstractApplicationContext实现
@Override
public ConfigurableEnvironment getEnvironment() {
if (this.environment == null) {
this.environment = createEnvironment(); <— — — — — — 11.进入
}
return this.environment;
}
- AbstractApplicationContext
protected ConfigurableEnvironment createEnvironment() {
return new StandardEnvironment(); <— — — — — — 12.返回
}
解释:暂时没有搞懂StandardEnvironment是干什么的。
- AnnotatedBeanDefinitionReader
// 回到AnnotatedBeanDefinitionReader构造方法
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry)); <— — — — — — 11.进入this
}
- 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);
- 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)
- AnnotationConfigApplicationContext
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
// 注册我们传过来的@Configuration的Java配置类的class
register(componentClasses); <— — — — — — 12.进入
refresh();
}
- AnnotationConfigApplicationContext
public void register(Class<?>... componentClasses) {
Assert.notEmpty(componentClasses, "At least one component class must be specified");
this.reader.register(componentClasses); <— — — — — — 13.进入
}
- AnnotatedBeanDefinitionReader
public void register(Class<?>... componentClasses) {
// 遍历传入的@Configuration的Java配置类的class,有可能有多个Java类
for (Class<?> componentClass : componentClasses) {
// 注册这些Java配置类
registerBean(componentClass); <— — — — — — 14.进入
}
}
- AnnotatedBeanDefinitionReader
public void registerBean(Class<?> beanClass) {
doRegisterBean(beanClass, null, null, null, null); <— — — — — — 15.进入
}
- 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);
至此:
- 把Java配置类读入
- 把该Java配置类转换为beanDefinition
- 把beanDefinition注册进BeanDefinitionRegistry
总结:现在我们有了以下成果:
- 有了BeanFactory实例
- BeanDefinitionRegistry里面已经注册了Java配置类的BeanDefinition,和一些其他内置bean的BeanDefinition
- AnnotationConfigApplicationContext
// 又回到了这里
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this(); //✅
register(componentClasses); //✅
refresh(); <— — — — — — 16.进入
}
阶段四(refresh方法、工厂后处理器的使用)
refresh()是整个Bean生命周期最重要的方法,没有之一。它的整个方法体就代表了从BeanDefinition的加工到Bean的实例化、最后到Bean的实例化、最后把Bean放入缓存池的过程。
⚠️注意:
- beanFactoryPostProcessors是ApplicationContext的一个成员变量
- beanPostProcessors是beanFactory的一个成员变量
(但是它们里面的元素不一定长期驻留)
- 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();
}
}
}