[关闭]
@survivorZzz 2019-07-05T01:08:10.000000Z 字数 20278 阅读 807

Spring 容器中的Bean

Spring


单例和多例

Spring 容器中 Bean的单例和多例大家应该都知道, 默认的, 注册到容器中的Bean是单例的,每一次从容器中获取这个Bean实例, 内存地址都是同一个 举证(亲测):

代码块1:
有这样一个类:

  1. public class MyClass implements InitializingBean, DisposableBean, BeanNameAware {
  2. private String beanName;
  3. public String getBeanName() {
  4. return beanName;
  5. }
  6. static {
  7. System.err.println(">>>>>>>>> static block");
  8. }
  9. {
  10. System.err.println(">>>>>>>>> non-static block");
  11. }
  12. @Override
  13. public void afterPropertiesSet() throws Exception {
  14. System.err.println(">>>>>>>>> afterPropertiesSet method!");
  15. }
  16. @PostConstruct
  17. void method() {
  18. System.err.println(">>>>>>>>> postConstruct method!");
  19. }
  20. @PreDestroy
  21. void preDestroy() {
  22. System.err.println(">>>>>>>>> preDestroy method!");
  23. }
  24. public void init() {
  25. System.err.println(">>>>>>>>> init method!");
  26. }
  27. public void destroyMethod() {
  28. System.err.println(">>>>>>>>> destroyMethod method!");
  29. }
  30. @Override
  31. public void destroy() {
  32. System.err.println(">>>>>>>>> override destroy method!");
  33. }
  34. @Override
  35. public void setBeanName(String s) {
  36. this.beanName = s;
  37. }
  38. }

代码块2:

  1. @SpringBootApplication
  2. //@ImportResource("springmvc.xml")
  3. public class DemoApplication implements ApplicationContextAware{
  4. static ApplicationContext applicationContext;
  5. public static void main(String[] args) {
  6. SpringApplication.run(DemoApplication.class, args);
  7. Object myClass1 = applicationContext.getBean(MyClass.class);
  8. Object myClass2 = applicationContext.getBean(MyClass.class);
  9. System.out.println(">>>>>>> 相等吗? " + (myClass1 == myClass2));
  10. }
  11. @Bean
  12. public MyClass myClass() {
  13. return new MyClass();
  14. }
  15. @Override
  16. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  17. if(this.applicationContext == null) {
  18. this.applicationContext = applicationContext;
  19. }
  20. }
  21. }

输出:

  1. >>>>>>>>> static block
  2. >>>>>>>>> non-static block
  3. >>>>>>>>> postConstruct method!
  4. >>>>>>>>> afterPropertiesSet method!
  5. >>>>>>>>> init method!
  6. >>>>>>> 相等吗? true

亲测, 默认的单例是容器一起来之后就立即实例化(lazy = false)的, 也就是说, 我把断点打在代码块2的第9行, 程序还没有跑到第9行的时候就已经打印出了前5行.

单例的Bean可以延迟实例化, 在@Bean注释下使用@Lazy(关于@Lazy的详细用法可以参考该注解的doc)后, 同样还是在代码块2的第9行断点, 当执行第9行的时候才会打印出以上输出的前5行.

测一测多例, 我们在@Bean注解下标注@Scope("prototype"), 代码块2变成:
代码块3:

  1. @SpringBootApplication
  2. //@ImportResource("springmvc.xml")
  3. public class DemoApplication implements ApplicationContextAware{
  4. static ApplicationContext applicationContext;
  5. public static void main(String[] args) {
  6. SpringApplication.run(DemoApplication.class, args);
  7. MyClass myClass1 = applicationContext.getBean(MyClass.class);
  8. MyClass myClass2 = applicationContext.getBean(MyClass.class);
  9. System.out.println(">>>>>>> 相等吗? " + (myClass1 == myClass2));
  10. }
  11. @Bean(initMethod = "init", destroyMethod = "destroyMethod")
  12. @Scope("prototype")
  13. public MyClass myClass() {
  14. return new MyClass();
  15. }
  16. @Override
  17. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  18. if(this.applicationContext == null) {
  19. this.applicationContext = applicationContext;
  20. }
  21. }
  22. }

输出:

  1. >>>>>>>>> static block
  2. >>>>>>>>> non-static block
  3. >>>>>>>>> postConstruct method!
  4. >>>>>>>>> afterPropertiesSet method!
  5. >>>>>>>>> init method!
  6. >>>>>>>>> non-static block
  7. >>>>>>>>> postConstruct method!
  8. >>>>>>>>> afterPropertiesSet method!
  9. >>>>>>>>> init method!
  10. >>>>>>> 相等吗? false

可以看到多例模式的Bean, 每次去容器中取到的都是一个新对象, 他们的内存地址不一样! 并且, 从输出的1-9行看出, 实例化了两次!
再来测一测多例的延迟实例化问题, 当我把断点打在代码块3的第9行, 程序跑完第8行准备跑第9行的时候, 控制台均没有输出, 当跑完第9行后, 控制台打印:

  1. >>>>>>>>> static block
  2. >>>>>>>>> non-static block
  3. >>>>>>>>> postConstruct method!
  4. >>>>>>>>> afterPropertiesSet method!
  5. >>>>>>>>> init method!

接着执行完第10行后打印:

  1. >>>>>>>>> non-static block
  2. >>>>>>>>> postConstruct method!
  3. >>>>>>>>> afterPropertiesSet method!
  4. >>>>>>>>> init method!

可以看出, 多例模式的Bean是延迟实例化的, 只有从容器中取Bean实例并引用它时才会去实例化它, 并且是每取一次, 就实例化一个对象出来.

那么问题来了, 如果我在多例的Bean上加上@Lazy(false)之后, 会不会在容器一起来之后就去实例化一次呢?
加了@Lazy(false)之后,在代码块3的第9行打断点, 当即将跑第9行时, 查看控制台, 并没有任何输出, 跑完第九行才打印出:

  1. >>>>>>>>> static block
  2. >>>>>>>>> non-static block
  3. >>>>>>>>> postConstruct method!
  4. >>>>>>>>> afterPropertiesSet method!
  5. >>>>>>>>> init method!

说明对于多例的Bean来说, 延迟实例化策略对多例Bean无意义. 多例Bean 都是延迟实例化的!


Spring 容器中Bean的生命周期

接着, 来探讨一下Spring容器中的Bean的生命周期.
直接上我自己的测试代码:
代码块1:
有这样一个Class定义:

  1. public class MyClass implements InitializingBean, DisposableBean, BeanNameAware {
  2. private String beanName;
  3. private int age;
  4. private String address;
  5. public MyClass() {
  6. System.err.println(">>>>>>>>>>> MyClass 无参数的构造方法执行!");
  7. }
  8. public MyClass(int age, String address) {
  9. System.err.println(">>>>>>>>>>> MyClass 带参数的构造方法执行!");
  10. this.age = age;
  11. this.address = address;
  12. }
  13. static {
  14. System.err.println(">>>>>>>>> 静态代码块执行");
  15. }
  16. {
  17. System.err.println(">>>>>>>>> 非静态代码块执行");
  18. }
  19. @Override
  20. public void afterPropertiesSet() throws Exception {
  21. System.err.println(">>>>>>>>> 重写InitializingBean的afterPropertiesSet执行!");
  22. }
  23. @PostConstruct
  24. void method() {
  25. System.err.println(">>>>>>>>> @PostConstruct标注的方法执行!");
  26. }
  27. @PreDestroy
  28. void preDestroy() {
  29. System.err.println(">>>>>>>>> @PreDestroy标注的方法执行!");
  30. }
  31. public void init() {
  32. System.err.println(">>>>>>>>> 自定义的init方法执行!");
  33. }
  34. public void destroyMethod() {
  35. System.err.println(">>>>>>>>> 自定义的destroy方法执行!");
  36. }
  37. @Override
  38. public void destroy() {
  39. System.err.println(">>>>>>>>> 重写DisposableBean的destroy方法执行!");
  40. }
  41. @Override
  42. public void setBeanName(String s) {
  43. System.err.println(">>>>>>>>> 重写BeanNameAware的setBeanName方法执行!");
  44. this.beanName = s;
  45. }
  46. public int getAge() {
  47. return age;
  48. }
  49. public void setAge(int age) {
  50. this.age = age;
  51. System.err.println(">>>>>>>>> MyClass 的setAge方法执行 set age = "+age+"!");
  52. }
  53. public String getAddress() {
  54. return address;
  55. }
  56. public void setAddress(String address) {
  57. this.address = address;
  58. System.err.println(">>>>>>>>> MyClass 的setAddress方法执行 set address = "+address+"!");
  59. }
  60. public String getBeanName() {
  61. return beanName;
  62. }
  63. }

代码块2
org.springframework.beans.factory.config.BeanPostProcessor的实现类:

  1. public class MyBeanPostPrecessor implements BeanPostProcessor {
  2. public MyBeanPostPrecessor() {
  3. super();
  4. System.err.println(">>>>>>>> BeanPostProcessor 实现类的 构造 方法执行");
  5. }
  6. @Override
  7. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  8. if(!(bean instanceof MyClass)) {
  9. return bean;
  10. }
  11. System.err.println(">>>>>>>> BeanPostProcessor 实现类的 postProcessBeforeInitialization 方法执行");
  12. return bean;
  13. }
  14. @Override
  15. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  16. if(!(bean instanceof MyClass)) {
  17. return bean;
  18. }
  19. System.err.println(">>>>>>>> BeanPostProcessor 实现类的 postProcessAfterInitialization 方法执行");
  20. return bean;
  21. }
  22. }

代码块3
org.springframework.beans.factory.config.BeanFactoryPostProcessor实现类:

  1. public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
  2. public MyBeanFactoryPostProcessor() {
  3. super();
  4. System.err.println(">>>>>>>> BeanFactoryPostProcessor 实现类的 构造 方法执行");
  5. }
  6. @Override
  7. public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
  8. System.err.println(">>>>>>>> BeanFactoryPostProcessor 实现类的 postProcessBeanFactory 方法执行");
  9. // String[] beanDefinitionNames = configurableListableBeanFactory.getBeanDefinitionNames();
  10. // for(String bd : beanDefinitionNames) {
  11. // //一些获取bean 定义信息的方法...
  12. // BeanDefinition beanDefinition = configurableListableBeanFactory.getBeanDefinition(bd);
  13. // MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
  14. // ConstructorArgumentValues constructorArgumentValues = beanDefinition.getConstructorArgumentValues();
  15. // String scope = beanDefinition.getScope();
  16. // // 一些修改Bean 定义信息的方法...
  17. // beanDefinition.setLazyInit(true);
  18. // beanDefinition.setScope("singleton");
  19. // }
  20. }
  21. }

代码块4
InstantiationAwareBeanPostProcessorAdapter适配器的子类:

  1. public class MyInstantiationAwareBeanPostProcessorAdapter extends InstantiationAwareBeanPostProcessorAdapter {
  2. public MyInstantiationAwareBeanPostProcessorAdapter() {
  3. super();
  4. System.err.println(">>>>>>>> 自定义的InstantiationAwareBeanPostProcessorAdapter 子类的 构造 方法执行");
  5. }
  6. @Override
  7. public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
  8. if(beanClass.isAssignableFrom(MyClass.class) || "myClass".equals(beanName)) {
  9. System.err.println(">>>>>>>> 自定义的InstantiationAwareBeanPostProcessorAdapter 子类的 postProcessBeforeInstantiation(Class<?> beanClass, String beanName) 方法执行");
  10. }
  11. return super.postProcessBeforeInstantiation(beanClass, beanName);
  12. }
  13. @Override
  14. public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
  15. if(bean instanceof MyClass || "myClass".equals(beanName)) {
  16. System.err.println(">>>>>>>> 自定义的InstantiationAwareBeanPostProcessorAdapter 子类的 postProcessAfterInstantiation(Object bean, String beanName) 方法执行");
  17. }
  18. return super.postProcessAfterInstantiation(bean, beanName);
  19. }
  20. @Override
  21. public PropertyValues postProcessPropertyValues(
  22. PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
  23. if(bean instanceof MyClass || "myClass".equals(beanName)) {
  24. System.err.println(">>>>>>>> 自定义的InstantiationAwareBeanPostProcessorAdapter 子类的 postProcessPropertyValues 方法执行,PropertyValues: "+ pvs.toString()+"");
  25. }
  26. return pvs;
  27. }
  28. }

代码块5
SpringBoot工程的启动类:

  1. @SpringBootApplication
  2. //@ImportResource("springmvc.xml")
  3. public class DemoApplication implements ApplicationContextAware, BeanFactoryAware {
  4. static ApplicationContext applicationContext;
  5. static BeanFactory beanFactory;
  6. public static void main(String[] args) {
  7. SpringApplication.run(DemoApplication.class, args);
  8. MyClass myClass = applicationContext.getBean(MyClass.class);
  9. BeanDefinitionRegistry beanDefinitionRegistry = (BeanDefinitionRegistry)DemoApplication.applicationContext;
  10. DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory)DemoApplication.beanFactory;
  11. BeanDefinition beanDefinition = defaultListableBeanFactory.getBeanDefinition(myClass.getBeanName());
  12. //从容器中移除MyClass的bean
  13. beanDefinitionRegistry.removeBeanDefinition(myClass.getBeanName());
  14. // MyClass myClass1 = applicationContext.getBean(MyClass.class);
  15. // System.err.println(myClass1.getBeanName());
  16. // 再次手动注册MyClass
  17. beanDefinitionRegistry.registerBeanDefinition(myClass.getBeanName(), beanDefinition);
  18. MyClass myClass2 = applicationContext.getBean(MyClass.class);
  19. System.err.println(">>>>>>>>> " + myClass2.getBeanName());
  20. }
  21. @Bean(initMethod = "init", destroyMethod = "destroyMethod")
  22. // @Scope("prototype")
  23. // @Lazy(false)
  24. public MyClass myClass() {
  25. return new MyClass(100, "广东");
  26. }
  27. @Bean
  28. public MyBeanFactoryPostProcessor myBeanFactoryPostProcessor() {
  29. return new MyBeanFactoryPostProcessor();
  30. }
  31. @Bean
  32. public MyBeanPostPrecessor myBeanPostPrecessor() {
  33. return new MyBeanPostPrecessor();
  34. }
  35. @Bean
  36. public MyInstantiationAwareBeanPostProcessorAdapter myInstantiationAwareBeanPostProcessorAdapter() {
  37. return new MyInstantiationAwareBeanPostProcessorAdapter();
  38. }
  39. @Override
  40. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  41. if(DemoApplication.applicationContext == null) {
  42. DemoApplication.applicationContext = applicationContext;
  43. }
  44. }
  45. @Override
  46. public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
  47. if(DemoApplication.beanFactory == null) {
  48. DemoApplication.beanFactory = beanFactory;
  49. }
  50. }
  51. }

启动代码块5后控制台输出:

  1. Connected to the target VM, address: '127.0.0.1:11931', transport: 'socket'
  2. . ____ _ __ _ _
  3. /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
  4. ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
  5. \\/ ___)| |_)| | | | | || (_| | ) ) ) )
  6. ' |____| .__|_| |_|_| |_\__, | / / / /
  7. =========|_|==============|___/=/_/_/_/
  8. :: Spring Boot :: (v2.0.6.RELEASE)
  9. >>>>>>>> BeanFactoryPostProcessor 实现类的 构造 方法执行
  10. >>>>>>>> BeanFactoryPostProcessor 实现类的 postProcessBeanFactory 方法执行
  11. >>>>>>>> BeanPostProcessor 实现类的 构造 方法执行
  12. >>>>>>>> 自定义的InstantiationAwareBeanPostProcessorAdapter 子类的 构造 方法执行
  13. >>>>>>>> 自定义的InstantiationAwareBeanPostProcessorAdapter 子类的 postProcessBeforeInstantiation(Class<?> beanClass, String beanName) 方法执行
  14. >>>>>>>>> 静态代码块执行
  15. >>>>>>>>> 非静态代码块执行
  16. >>>>>>>>>>> MyClass 带参数的构造方法执行!
  17. >>>>>>>> 自定义的InstantiationAwareBeanPostProcessorAdapter 子类的 postProcessAfterInstantiation(Object bean, String beanName) 方法执行
  18. >>>>>>>> 自定义的InstantiationAwareBeanPostProcessorAdapter 子类的 postProcessPropertyValues 方法执行,PropertyValues: PropertyValues: length=0
  19. >>>>>>>>> 重写BeanNameAwaresetBeanName方法执行!
  20. >>>>>>>> BeanPostProcessor 实现类的 postProcessBeforeInitialization 方法执行
  21. >>>>>>>>> @PostConstruct标注的方法执行!
  22. >>>>>>>>> 重写InitializingBeanafterPropertiesSet执行!
  23. >>>>>>>>> 自定义的init方法执行!
  24. >>>>>>>> BeanPostProcessor 实现类的 postProcessAfterInitialization 方法执行
  25. >>>>>>>>> @PreDestroy标注的方法执行!
  26. >>>>>>>>> 重写DisposableBeandestroy方法执行!
  27. >>>>>>>>> 自定义的destroy方法执行!
  28. >>>>>>>> 自定义的InstantiationAwareBeanPostProcessorAdapter 子类的 postProcessBeforeInstantiation(Class<?> beanClass, String beanName) 方法执行
  29. >>>>>>>>> 非静态代码块执行
  30. >>>>>>>>>>> MyClass 带参数的构造方法执行!
  31. >>>>>>>> 自定义的InstantiationAwareBeanPostProcessorAdapter 子类的 postProcessAfterInstantiation(Object bean, String beanName) 方法执行
  32. >>>>>>>> 自定义的InstantiationAwareBeanPostProcessorAdapter 子类的 postProcessPropertyValues 方法执行,PropertyValues: PropertyValues: length=0
  33. >>>>>>>>> 重写BeanNameAwaresetBeanName方法执行!
  34. >>>>>>>> BeanPostProcessor 实现类的 postProcessBeforeInitialization 方法执行
  35. >>>>>>>>> @PostConstruct标注的方法执行!
  36. >>>>>>>>> 重写InitializingBeanafterPropertiesSet执行!
  37. >>>>>>>>> 自定义的init方法执行!
  38. >>>>>>>> BeanPostProcessor 实现类的 postProcessAfterInitialization 方法执行
  39. >>>>>>>>> myClass

这里说一下org.springframework.beans.factory.config.BeanPostProcessor接口, 它是一个顶层接口, 该接口定义如下:

  1. public interface BeanPostProcessor {
  2. default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  3. return bean;
  4. }
  5. default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  6. return bean;
  7. }
  8. }

该接口的许多Spring内置的实现类例如AutowiredAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor,ServletContextAwareProcessor是Spring 容器启动时, 容器自己实例化并调用的,例如AutowiredAnnotationBeanPostProcessor用于扫描一个Bean中被@AntoWired标注的成员属性或setter方法或构造器以在实例化Bean时进行依赖注入. 从以上的控制台输出顺序可以看到, 该接口的postProcessBeforeInitialization方法和postProcessAfterInitialization方法在Bean的生命周期的执行顺序为:

1. Bean的构造方法, 此时Bean的实例已经创建(亲测, 可以自己debug试试看)
2. `BeanPostProcessor`的`postProcessBeforeInitialization`方法
3. Bean类中`@PostConstruct`标注的方法(如果有)
4. Bean类中重写`InitializingBean`接口的`afterPropertiesSet()`方法(如果有)
5. Bean中自定义的`init`方法, 并在`@Bean(initMethod = 'init')`指定(如果有)
6. `BeanPostProcessor`的`postProcessAfterInitialization`方法

以上顺序, 对实例化在Spring容器中的Bean都适用, 也就是说, 以上代码块3中的两个方法在每一个Bean实例化之后都会执行, 所以, 可以通过自定义该接口的实现类来对实例化后的对象做一些操作. Spring本身已经提供很多实现类, 具体功能, 可自己源码探索.

再接着, 顺带再说一下另一个BeanPostProcessor的子接口InstantiationAwareBeanPostProcessor, 该子接口除了具备BeanPostProcessor的两个方法定义之外, 还有以下几个方法:

  1. //该方法在构造方法执行之前(Bean实例化之前)执行
  2. default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
  3. return null;
  4. }
  5. //该方法在构造方法执行之后(Bean实例化后)执行
  6. default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
  7. return true;
  8. }
  9. //该方法在属性注入时可对注入的属性进行操作
  10. default PropertyValues postProcessPropertyValues(
  11. PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
  12. return pvs;
  13. }

以上代码中注释所说的意思, 从以上控制台输出中可以得到验证.该接口有一个适配器**InstantiationAwareBeanPostProcessorAdapter, 可以继承该适配器,重写里面的方法对Bean实例化前后的时间点做一些操作.

接着再说一下和Bean的生命周期无关, 但是和Spring 容器的生命周期有关的BeanFactoryPostProcessor接口.该接口定义如下:

  1. @FunctionalInterface
  2. public interface BeanFactoryPostProcessor {
  3. /**
  4. * Modify the application context's internal bean factory after its standard
  5. * initialization. All bean definitions will have been loaded, but no beans
  6. * will have been instantiated yet. This allows for overriding or adding
  7. * properties even to eager-initializing beans.
  8. * @param beanFactory the bean factory used by the application context
  9. * @throws org.springframework.beans.BeansException in case of errors
  10. */
  11. void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
  12. }

从以上的控制台输出顺序可以看出, 该接口实现类的postProcessBeanFactory方法是在Bean初始化之前执行的, 查看该接口方法的注释可知该方法是在所有的Bean定义信息加载但还没有任何Bean被实例化时执行的.那问题就来了, 这个接口和BeanPostProcessor接口有什么区别?以及使用场景如何呢?

  1. BeanFactoryPostProcessor的实现类是作为我们常说的Spring Bean来实例化, 但是这些实现类的对象不作为其他Bean生命周期的一部分, 而是Spring 容器生命周期的一部分.
  2. 由于BeanFactoryPostProcessorpostProcessBeanFactory被回调的时机是在Bean定义信息被加载时, 在其他Bean被实例化前. 所以你可以在获取到所有的Bean定义, 并修改或重写一些某些Bean 定义,即使是"eager-initializing"的Bean 定义也可以在这个时候修改, 例如这个例子:

    1. public class CustomBeanFactory implements BeanFactoryPostProcessor {
    2. @Override
    3. public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
    4. System.err.println(">>>>>>>> BeanFactoryPostProcessor 实现类的 postProcessBeanFactory 方法执行");
    5. String[] beanDefinitionNames = configurableListableBeanFactory.getBeanDefinitionNames();
    6. for(String bd : beanDefinitionNames) {
    7. //一些获取bean 定义信息的方法...
    8. BeanDefinition beanDefinition = configurableListableBeanFactory.getBeanDefinition(bd);
    9. MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
    10. ConstructorArgumentValues constructorArgumentValues = beanDefinition.getConstructorArgumentValues();
    11. String scope = beanDefinition.getScope();
    12. // 一些修改Bean 定义信息的方法...
    13. beanDefinition.setLazyInit(true);
    14. beanDefinition.setScope("singleton");
    15. }
    16. }
    17. }
  3. BeanPostProcessor中的两个方法是在Bean实例已经创建之后执行.

顺带再记录一下看源码过程中, SpringBoot启动的时候做的一些事情.
SpringBoot通过SpringApplication.run(DemoApplication.class, args);开始启动Spring, 经过若干操作之后调用了SpringApplication类中public ConfigurableApplicationContext run(String... args)方法,该方法如下:

  1. public ConfigurableApplicationContext run(String... args) {
  2. StopWatch stopWatch = new StopWatch();
  3. stopWatch.start();
  4. ConfigurableApplicationContext context = null;
  5. Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
  6. this.configureHeadlessProperty();
  7. SpringApplicationRunListeners listeners = this.getRunListeners(args);
  8. listeners.starting();
  9. Collection exceptionReporters;
  10. try {
  11. ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
  12. ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
  13. this.configureIgnoreBeanInfo(environment);
  14. Banner printedBanner = this.printBanner(environment);
  15. context = this.createApplicationContext();
  16. exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
  17. this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
  18. this.refreshContext(context);
  19. this.afterRefresh(context, applicationArguments);
  20. stopWatch.stop();
  21. if (this.logStartupInfo) {
  22. (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
  23. }
  24. listeners.started(context);
  25. this.callRunners(context, applicationArguments);
  26. } catch (Throwable var10) {
  27. this.handleRunFailure(context, var10, exceptionReporters, listeners);
  28. throw new IllegalStateException(var10);
  29. }
  30. try {
  31. listeners.running(context);
  32. return context;
  33. } catch (Throwable var9) {
  34. this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
  35. throw new IllegalStateException(var9);
  36. }
  37. }

额外的, 注意这个方法的16行, 创建一个ApplicationContext接口的实现类org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext对象(看源码可知, 只要classpath路径中包含javax.servlet.Servletorg.springframework.web.context.ConfigurableWebApplicationContext 就会创建这个类型的ApplicationContext对象作为上下文).
19this.refreshContext(context), 这段代码之后做的事情就是将生成的ApplicationContext对象强转成org.springframework.context.support.AbstractApplicationContext, 然后调用这个抽象类的org.springframework.context.support.AbstractApplicationContext#refresh方法, 该方法体部分代码如下(没有贴try-catch块):

  1. public void refresh() throws BeansException, IllegalStateException {
  2. // Allows post-processing of the bean factory in context subclasses.
  3. postProcessBeanFactory(beanFactory);
  4. // Invoke factory processors registered as beans in the context.
  5. invokeBeanFactoryPostProcessors(beanFactory);
  6. // Register bean processors that intercept bean creation.
  7. registerBeanPostProcessors(beanFactory);
  8. // Initialize message source for this context.
  9. initMessageSource();
  10. // Initialize event multicaster for this context.
  11. initApplicationEventMulticaster();
  12. // Initialize other special beans in specific context subclasses.
  13. onRefresh();
  14. // Check for listener beans and register them.
  15. registerListeners();
  16. // Instantiate all remaining (non-lazy-init) singletons.
  17. finishBeanFactoryInitialization(beanFactory);
  18. // Last step: publish corresponding event.
  19. finishRefresh();
  20. }

看第6行和第9行,第6行所做的事情就是依照顺序执行了注册在上下文中的所有BeanFactoryPostProcessor 接口的对象的void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) 方法以在BeanDefinition被容器加载时做一些操作,包括我自定义的'MyBeanFactoryPostProcessor'的postProcessBeanFactory方法, 这些BeanFactoryPostProcessor对象的执行有顺序, 如何排序, 可追踪以上代码块中invokeBeanFactoryPostProcessors(beanFactory);方法的执行, 不再多说.
9行, 所做的事情就是将所有的BeanPostProcessor接口的实现类对象注册到beanFactory上, 以在接下来容器实例化Bean之后按照一定顺序执行实例化post和after方法, 至于我这里所谓的顺序,详情可追踪这段代码的执行.


总结
Spring 容器从启动到用户从容器中取一个Bean对象实例并引用它这个过程做个简单的总结, 顺序如下:
1. 注册到容器中的所有接口BeanFactoryPostProcessor(该接口的主要作用是可以在Bean实例化之前, 修改已经加载的BeanDefinition)的实现类被实例化.
2. 1中所指的实例化对象按照顺序执行postProcessBeanFactory方法.
3. 所有注册到容器中的BeanPostProcessor的实现类被实例化.
4. 在一个普通Bean被容器实例化之前, BeanPostProcessor接口的子接口InstantiationAwareBeanPostProcessor的实现类的实例化对象的postProcessBeforeInstantiation方法执行.
5. 一个普通Bean的静态代码块被执行(意味着类加载器开始加载这个类的.class文件)
6. 一个普通Bean被容器实例化, 先执行非静态代码块, 再执行构造方法.
7. InstantiationAwareBeanPostProcessor的实现类的实例化对象的postProcessAfterInstantiation方法执行.
8. InstantiationAwareBeanPostProcessor的实现类的实例化对象的postProcessPropertyValues方法执行.
9. 如果该普通Bean实现了Aware接口的子接口, 例如BeanNameAware, 则这些aware接口的方法执行.
10. 注册到容器中的各个接口BeanPostProcessor的的实现类的postProcessBeforeInitialization方法执行.
11. 普通Bean中@PostConstruct标注的方法执行(如果有).
12. 如果普通Bean实现了InitializingBean接口, 则afterPropertiesSet方法执行.
13. 自定义的init方法执行!
14. BeanPostProcessor 实现类的 postProcessAfterInitialization 方法执行.
15. 从容器中移除一个Bean
15. @PreDestroy标注的方法执行(如果有).
16. 如果普通Bean实现了DisposableBean接口则destroy方法执行.
17. 自定义的destroy方法执行!


欢迎各位大佬多多交流, 不正之处欢迎指正!
书写不易, 如想转载请 注明原文地址:
https://www.zybuluo.com/survivorZzz/note/1314637

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注