1.BeanFactory和ApplicationContext
我们先查看ApplicationContext的类图吧(IDEA快捷键Ctrl+Alt+U)
我们会发现BeanFactory是Application的父类,那么他们两者有什么区别呢
我们先来了解他们的作用
BeanFactory:
是Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能;
ApplicationContext:
应用上下文,继承BeanFactory所有的功能,它是Spring的一各更高级的容器,提供了更多的有用的功能;
- 国际化(MessageSource)
- 访问资源,如URL和文件(ResourceLoader)
- 载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层
- 消息发送、响应机制(ApplicationEventPublisher)
- AOP(拦截器)
两者装载bean的区别
BeanFactory:
BeanFactory在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化;
ApplicationContext:
ApplicationContext在启动的时候就把所有的Bean全部实例化了。
延迟实例化的优点:(BeanFactory)
应用启动的时候占用资源很少;对资源要求较高的应用,比较有优势;
不延迟实例化的优点: (ApplicationContext)
- 所有的Bean在启动的时候都加载,系统运行的速度快;
- 在启动的时候所有的Bean都加载了,我们就能在系统启动的时候,尽早的发现系统中的配置问题
- 建议web应用,在启动的时候就把所有的Bean都加载了。
2.AnnotationConfig启动方式解析
创建MyConfig.java
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyConfig {
}
Application.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContextExtensionsKt;
public class Application {
public static void main(String[] args) {
// ApplicationContext
new AnnotationConfigApplicationContext(MyConfig.class);
}
}
源码查看AnnotationConfigApplicationContext
进入的此词方法,说明我们启动需要先经过这三个方法,我们先来看this(),点击查看
跳转到无参构造中来,但是,我们看方法必须要先看类,看他是否有继承(这点很重要,因为作为子类,执行之前都得先执行父类),所以跳转过来,我们会发现AnnotationConfigApplicationContext继承了GenericApplicationContext。
这个很重要,后面我们会用到
好了,我们再次回到this.reader,this.scanner。他们两个很好理解,一个是读取(注解),一个是扫描(扫包)
this()看完了,
接下来看this.register(annotatedClasses)
好了,终于到头了
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
// 我们之前学习过RootBeanDefinition,它是用于传统方式往IOC容器注入bean
// 一样的 AnnotatedGenericBeanDefinition 属于注解方式注入bean
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
// 判断是否使用condition 条件注册
if (!this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
// 用于创建bean实例的回调
abd.setInstanceSupplier(instanceSupplier);
// 解析bean作用域(单例或者原型),如果有@Scope注解,则解析@Scope,没有则默认为singleton
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
// 作用域写回BeanDefinition数据结构, abd中缺损的情况下为空,将默认值singleton重新赋值到abd
abd.setScope(scopeMetadata.getScopeName());
// 生成bean配置类beanName
String beanName = name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry);
// 通用注解解析到abd结构中,主要是处理Lazy, primary DependsOn, Role ,Description这五个注解
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
int var10;
int var11;
// @Qualifier特殊限定符处理,@Qualifier 除了bean类级别的限定符之外,要考虑的限定符特定限定符注释
if (qualifiers != null) {
Class[] var9 = qualifiers;
var10 = qualifiers.length;
for(var11 = 0; var11 < var10; ++var11) {
Class<? extends Annotation> qualifier = var9[var11];
if (Primary.class == qualifier) {
// 如果配置@Primary注解,则设置当前Bean为自动装配autowire时首选bean
abd.setPrimary(true);
} else if (Lazy.class == qualifier) {
// 设置当前bean为延迟加载
abd.setLazyInit(true);
} else {
// //其他注解,则添加到abd结构中
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
BeanDefinitionCustomizer[] var13 = definitionCustomizers;
var10 = definitionCustomizers.length;
// 自定义bean注册,通常用在applicationContext创建后,手动向容器中一lambda表达式的方式注册bean
for(var11 = 0; var11 < var10; ++var11) {
BeanDefinitionCustomizer customizer = var13[var11];
// //自定义bean添加到BeanDefinition
customizer.customize(abd);
}
// 根据beanName和bean定义信息封装一个beanHolder,beanHolder其实就是一个 beanname和BeanDefinition的映射
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
// 根据注解Bean定义类中配置的作用域@Scope注解的值,为Bean定义应用相应的代理模式
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 按名称将bean定义信息注册到容器中,实际上DefaultListableBeanFactory内部维护一个Map<String, BeanDefinition>类型变量beanDefinitionMap beanDefinitionMap用来保存beanName,BeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}
register方法重点完成了bean配置类本身的基本信息注册
接下来看this.refresh()
----后期补充-----