BeanFactory和ApplicationContext的作用和区别
- BeanFactory负责读取bean配置文档,管理bean的加载,实例化,维护bean之间的依赖关心,负责bean的生命周期
- ApplicationContext继承BeanFactory,除了BeanFactory所提供的功能之外,还提供了更完整的框架功能
AnnotationConfigApplicationContex
AnnotationConfigApplicationContex的类图
基于注解
package com.mayikt.v3;
import com.mayikt.v3.config.MySpringConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @Description:
* @Author: ChenYi
* @Date: 2020/07/02 23:16
**/
public class Test03 {
private static AnnotationConfigApplicationContext annotationConfigApplicationContext;
public static void main(String[] args) {
//基于注解创建上下文对象
annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MySpringConfig.class);
}
}
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
//里面会先调用父类的GenericApplicationContext无参构造函数创建一个new DefaultListableBeanFactory()对象
this();
//注意这里只是把注解的配置类注入ioc容器中,其他的对象在这个方法中是还没有开始注入的
register(annotatedClasses);
refresh();
}
GenericApplicationContext的无参构造函数
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
Register方法的执行流程
BeanDefinition是定义 Bean 的配置元信息接口,类图
把注解的配置类放到ioc容器中
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
//注解的方式注入ioc中bean的信息
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
//判断是否有加Condition注解,有条件的注入对象
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
//设置回调
abd.setInstanceSupplier(instanceSupplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
//设置是否单例还是多例
abd.setScope(scopeMetadata.getScopeName());
//获取beanId 没有的话就使用类的小写
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
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));
}
}
}
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
customizer.customize(abd);
}
//把AnnotatedGenericBeanDefinition封装成一个对象
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//把注解方式的配置类注册到ioc容器中
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
流程图
基于扫包
package com.mayikt.v3;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @Description:
* @Author: ChenYi
* @Date: 2020/07/02 23:16
**/
public class Test03 {
private static AnnotationConfigApplicationContext annotationConfigApplicationContext;
public static void main(String[] args) {
//基于扫包创建上下文对象
annotationConfigApplicationContext = new AnnotationConfigApplicationContext("com.mayikt.v2");
}
}
public AnnotationConfigApplicationContext(String... basePackages) {
//里面会先调用父类的GenericApplicationContext无参构造函数创建一个new DefaultListableBeanFactory()对象
this();
//基于扫包的注入对象的方法
scan(basePackages);
refresh();
}
Spring的父子容器
- 子容器可以访问父容器中bean,父容器无法访问子容器中的bean
- BeanFactory接口支撑层次查找
- ListableBeanFactory接口不支持层次查找
- BeanFactoryUtils工具类中提供了一些非常使用的方法,比如支持bean层次查找的方法等等
- 通常我们使用的spirngmvc的时候,采用3层结构,controller层、service层、dao层,父容器中会包含dao层和service层,而子容器中包含的只有controller层,这2个容器组成了父子容器的关系,controller层通常会注入service层的bean,采用父子容器可以避免有些人在service层去注入controller层的bean,导致整个依赖层次比较混乱的
参考:蚂蚁课堂