spring源码-生命周期

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 的方法。

FileSystemXmlApplicationContext:从文件系统或者 url 指定的 xml 配置文件创建,参数为配置文件名或文件名数组。
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
在这里插入图片描述

5、doRegisterBean 方法介绍
该方法会注册bean到IOC容器中去。

private<T> void doRegisterBean(Class<T> beanClass,@Nullable String name,
@Nullable Class<?extends Annotation>[]qualifiers,@Nullable Supplier<T> 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=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<?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);
        }
        }
        //封装 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没有销毁方法)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fOaOajs4-1645151553934)(img_33.png)]在这里插入图片描述


在这里插入图片描述


什么时候bean执行销毁?
答:异常报错的时候、执行applicationContext的 close 方法

ApplicationContextAware接口

在servlet过滤器中不可以使用注解方式获取 bean 对象。需要自己单独获取上下文 applicationContext
在这里插入图片描述

后置处理器 BeanPostProcessor

作用:可以对初始化实现增强。

SpringBean的生命周期总结

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值