Spring学习笔记:Bean初始化

您所在的位置:网站首页 唐璇做了什么事 Spring学习笔记:Bean初始化

Spring学习笔记:Bean初始化

2024-06-22 20:53| 来源: 网络整理| 查看: 265

本文是自己学习的一个总结

这里写目录标题 1、bean初始化简介1.1、bean的初始化发生在什么阶段,做了什么事 2、Bean初始化的回调函数2.1、基于@PostConstruct,构造后回调函数2.1.1、使用@PostConstruct2.1.2、同一个类中使用多个@PostConstruct2.1.3、注解生效范围 2.2、实现InitInitializingBean覆写afterPropertiesSet2.2.1、afterPropertiesSet的生效范围 2.3、基于@Bean的initMethod属性,初始化后回调函数2.3.1、initMethod的生效范围 2.4、@PostConstruct,afterPropertiesSet和initMethod的执行顺序 3、bean的延迟初始化3.1、bean设置延迟初始化的方式3.2、延迟初始化的时机和非延迟初始化的时机

1、bean初始化简介 1.1、bean的初始化发生在什么阶段,做了什么事

当我们从xml文件或者注解中生成容器时,XML文件或者注解中描述的bean就完成了初始化。

所谓初始化,就是bean的元信息加载进容器,说具体也就是bean信息由xml文件或者注解中读取出来,加载为BeanDefinition,再通过BeanDefinitionRegistry将这些BeanDefiniton注册到容器中的过程。

其中,这个初始化过程又可以分为构造->属性填充->初始化完成,这三个阶段又分别对应着接下来的三类回调函数。

2、Bean初始化的回调函数 2.1、基于@PostConstruct,构造后回调函数 2.1.1、使用@PostConstruct

@PostConstruct,从名字上看就能知道,是bean完成初始化之后的回调注解。该注解的使用方式如下,在即将被成为Bean的类A中实现一个方法,并用@PostContruct标注这个方法,那么这个方法就是类A作为Bean完成初始化之后的回调方法。类A作为bean在容器中初始化之后,会调用被@PostContruct标注的方法。

我们看看例子。 DefaultUserFactory的实现如下,这是我们要注册为Bean的类。

@Component public class DefaultUserFactory { @PostConstruct public void init() { System.out.println("@PostConstruct:UserFactory 初始化"); } }

之后在和DefaultUserFactory同一个包下定义扫描类。

@ComponentScan public class ConfigScan {}

最后根据扫描类生成容器,我们看系统对DefaultUserFactory完成初始化后会不会调用init()函数。

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigScan.class);

最后打印结果如下,回调函数成功调用。 在这里插入图片描述

2.1.2、同一个类中使用多个@PostConstruct

@PostConstruct在类中使用标注方法,当这个类被初始化成bean之后就会调用@PostConstruct标注的方法。

其中,@PostConstruct可以在类中标注多个方法,并且类被初始化成bean之后,所有被@PostConstruct标注的方法都会被回调,但是调用的顺序不能保证,并不是按定义顺序调用的,系统似乎有自己的一套规则。

2.1.3、注解生效范围

@PostConstruct在类A 中使用,那只有类A是通过注解的方式初始化成bean时,@PostConstruct才会生效。

但是如果类A是通过XML初始化成bean,那@PostConstruct就不会起作用。

2.2、实现InitInitializingBean覆写afterPropertiesSet

若类A要被注册为bean,那可令类A实现InitInitializingBean接口,覆写其中的afterPropertiesSet方法。这样A作为bean在初始化阶段中,属性填充以后,会回调覆写的afterPropertiesSet方法。

基于上面的代码,我们在DefaultUserFactory中加入afterPropertiesSet相关的代码

@Component public class DefaultUserFactory implements UserFactory, InitializingBean { @PostConstruct public void init() { System.out.println("@PostConstruct:UserFactory 初始化"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("afterPropertiesSet:DefaultUserFactory初始化"); } }

扫描类和生成容器的代码不变。

public class ConfigScan {} ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigScan.class);

最后输出结果如下 在这里插入图片描述

2.2.1、afterPropertiesSet的生效范围

实现InitInitializingBean覆写afterPropertiesSet,这个方法与@PostConstruct不同,无论是通过注解还是通过xml,afterPropertiesSet都可以生效。

2.3、基于@Bean的initMethod属性,初始化后回调函数

@Bean中有个属性是initMethod,他是用来将类中的某个方法指定为初始化函数。我们看看例子。

接着上面的代码,我们在DefaultUserFactory中加入@Bean相关的代码

@Component public class DefaultUserFactory implements UserFactory{ @PostConstruct public void init() { System.out.println("@PostConstruct:UserFactory 初始化"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("afterPropertiesSet:DefaultUserFactory初始化"); } @Bean(initMethod = "initFactory") public DefaultUserFactory getDefaultUserFactory() { return new DefaultUserFactory(); } public void initFactory() { System.out.println("@Bean.initMethod:DefaultUserFactory初始化"); } }

可以预测,最后生成的容器中有两个类型为DefaultUserFactory的Bean。一个是基于@Component生成的bean,这个bean只设置了@PostConstruct和afterProperties的回调函数;另一个是基于@Bean生成的bean,这个类不仅有@PostConstruct和afterProperties的回调函数,还有initMethod的回调函数。

扫描类和生成容器的代码不变。

public class ConfigScan {} ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigScan.class);

最后输出结果如下

在这里插入图片描述

2.3.1、initMethod的生效范围

因为这也是基于注解实现的,所以只有容器是通过注解生成时initMethod才有效,通过xml生成容器时initMethod会无效。

2.4、@PostConstruct,afterPropertiesSet和initMethod的执行顺序

文章开头说过,bean的初始化又分为构造->属性填充->初始化,而以上三种方式就对应着这三个阶段。

@PostConstruct在构造结束后会被调用,afterPropertiesSet在属性填充后会被调用,initMethod在初始化完成后会被调用。

3、bean的延迟初始化 3.1、bean设置延迟初始化的方式

一般来说说只有两种,一种是xml中设置,另一种是注解中设置。

@Lazy(true) 3.2、延迟初始化的时机和非延迟初始化的时机

延迟初始化是在容器启动之后,需要实例化bean时才会初始化这个bean,而非延迟初始化则是在容器启动是就完成初始化。

我们在上面代码的基础上给DefaultUserFactory加上@Lazy注解

@Lazy public class DefaultUserFactory implements InitializingBean{···}

同时在启动容器的语句之后加上一段输出语句表示容器启动了,然后实例化defaultUserFactory。

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigScan.class); System.out.println("容器启动了"); applicationContext.getBean("defaultUserFactory");

最后输出语句是 在这里插入图片描述 可以看出,defaultUserFactory是在容器启动后,需要实施化时才去初始化。

如果DefaultUserFactory没有@Lazy注解,输出语句则是下图所示,初始化在容器启动时。

在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3