Spring学习笔记:Bean初始化 |
您所在的位置:网站首页 › 唐璇做了什么事 › Spring学习笔记:Bean初始化 |
本文是自己学习的一个总结 这里写目录标题 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);最后打印结果如下,回调函数成功调用。 @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);最后输出结果如下 实现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);最后输出结果如下 因为这也是基于注解实现的,所以只有容器是通过注解生成时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没有@Lazy注解,输出语句则是下图所示,初始化在容器启动时。 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |