BeanFactory和ApplicationContext的区别 Spring 有两个核心的接口:BeanFactory 和 ApplicationContext,其中 ApplicationContext 是BeanFactory 的子接口/它们都可以代表 Spring 容器,Spring 容器时生成Bean 实例的工厂,并且管理容器中的 Bean。
如何生成类图?
idea:ctrl + atl + u
BeanFactory和ApplicationContext的作用和区别
作用:
1、BeanFactory 负责读取 bean 配置文档,管理 bean 的加载,实例化,维护 bean 之间的依赖关系,负责 bean 的生命周期。
2、ApplicationContext 除了提供上述 BeanFactory 所能提供的功能之外,还提供了更完整的框架功能。
- 国际化支持
- 资源访问:
Resource rs = ctx.getResource("classpath:config.properties");
- 事件传递:通过实现 ApplicationContextAware 接口。
- 常用的获取 ApplicationContext 的方法。
ClassPathXmlApplicationContext:从classpath 的xml 配置文件创建,可以从 jar 包中读取配置文件。
WebApplicationContextUtils:从 web 应用的跟目录读取配置文件,需要先在 web.xml 中配置,可以配置监听器或者 servlet 来实现。
AnnotationApplicationContext 是基于注解来使用的,它不需要配置文件,采用 java 配置类和各种注解来配置,是比较简单的方式。
AnnotationConfig启动流程源码分析 分析前须知:
1、配置文件类也会注入到IOC容器中。
2、通过Java的多态机制,子类的无参构造函数执行时,先执行父类的无参构造函数。
3、BeanDefinition 作用:bean的信息描述、获取api,AnnotatedGenericBeanDefinition 作用:表示注解方式启动注入配置类
文章图片
源码流程分析:
1、基于注解启动,通过有参构造函数(参数为配置类方式)
java类MyConfig 中配置了扫包范围、【@Import注解注入的bean】等等。
//基于注解启动
ApplicationContext applicationContext=new AnnotationConfigApplicationContext(MyConfig.class);
2、AnnotationConfigApplicationContext 调用自己的无参构造函数
有参构造函数
文章图片
无参构造函数
文章图片
调用父类 GenericApplicationContext 的无参构造函数
文章图片
文章图片
3、执行
register(componentClasses);
注册方法文章图片
文章图片
for循环
文章图片
4、通过 doRegisterBean 方法注册bean
文章图片
【spring源码|spring源码-生命周期】5、doRegisterBean 方法介绍
该方法会注册bean到IOC容器中去。
private void doRegisterBean(Class beanClass,@Nullable String name,
@Nullable Class[]qualifiers,@Nullable Supplier supplier,
@Nullable BeanDefinitionCustomizer[]customizers){
//1、AnnotatedGenericBeanDefinition 注解方式启动的配置注入 ioc bean 信息
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
//2、判断是否有使用 condition 条件注入 bean
if(this.conditionEvaluator.shouldSkip(abd.getMetadata())){
return;
}
//3、设置回调方式
abd.setInstanceSupplier(supplier);
//4、判断config 类上是否有加上 @Scope 作用域
ScopeMetadata scopeMetadata=https://www.it610.com/article/this.scopeMetadataResolver.resolveScopeMetadata(abd);
//5、设置 scope
abd.setScope(scopeMetadata.getScopeName());
//6、判断是否有传递 beanname,如果没有传递name的话,生成beanname 默认类名小写作为beanid
String beanName=(name!=null?name:this.beanNameGenerator.generateBeanName(abd,this.registry));
//7、判断是否有其他注解:Lazy、Primary、DependsOn、Role、Description,有的话给 adb 对应属性赋值。
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if(qualifiers!=null){
for(Class 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);
}
}
//封装 BeanDefinitionHolder 注册 BeanDefinition 到IOC容器中
BeanDefinitionHolder definitionHolder=new BeanDefinitionHolder(abd,beanName);
definitionHolder=AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata,definitionHolder,this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder,this.registry);
}
执行完 registerBeanDefinition 方法后,Bean 的名称和对应的 BeanDefinition(Bean 的信息) 就被放入了容器中,
后续获取 Bean 也是从这个容器中获取。
单例和多例 单例:容器在创建的时候会初始化,默认是单例。
多例:从容器中获取对象的时候再初始化。
判断对象在什么时候初始化?
答:在类的无参构造函数里面输出内容就可以发现了。
对象的初始化与销毁 SpringBean 的生命周期: Bean的创建 --》初始化–》销毁过程。
可以自定义方法与销毁的方法。
配置bean的初始化、销毁方法的方式
方法一:通过 @Bean 指定 init-methed 和 destroy-method;
方法二:通过 Bean 实现 InitalizingBean (定义初始化逻辑),DisposableBean(定义销毁逻辑);
方法三:可以使用JSR250:
- @PostConstruct:在bean 创建完成并且属性赋值完成,来执行初始化方法。
- @PreDestroy:在容器销毁 bean 之前通知我们来进行清理工作。
答:bean初始化,指的就是对象已经创建,里面的所有的set方法都已经执行完毕了;指定方法执行
@Bean 注解中可以指定bean的初始化后方法(initMethod():对象创建之后,构造函数执行之后,才执行这个初始化方法)和销毁后方法(destroyMethod():多例bean没有销毁方法)
文章图片
文章图片
文章图片
什么时候bean执行销毁?
答:异常报错的时候、执行applicationContext的 close 方法
ApplicationContextAware接口 在servlet过滤器中不可以使用注解方式获取 bean 对象。需要自己单独获取上下文 applicationContext
文章图片
后置处理器 BeanPostProcessor
作用:可以对初始化实现增强。
SpringBean的生命周期总结
文章图片
推荐阅读
- 算法|面试时遇到一致性哈希算法这样回答会让面试官眼前一亮
- java—water—NIO和AIO
- spring初始化&循环引用
- Android|【Android】EditText的简单登录界面设计
- Java毕业设计项目实战篇|Java项目:(小程序)物业管理系统(spring+spring mvc+mybatis+layui+微信小程)
- Java|跳槽来的00后真是卷王,起薪18k都快赶上我了
- java|全网首发阿里内部Spring Security项目实战搭建
- Java|Java基础——数组
- 人工智能|干货!人体姿态估计与运动预测