• Spring Bean初始化


    一、Bean的生命周期

    如何记忆 Spring Bean 的生命周期

    二、Spring初始化Bean几种方式

    1、初始化介绍

    执行顺序:Constructor > @PostConstruct > InitializingBean > init-method

    • 实现InitializingBean接口,重写afterPropertiesSet方法

    • 元素上添加init-method初始化

    • 使用@PostConstruct注解

    2、@PostConstruct注解

    javaEE5引入了@PostConstruct和@PreDestroy两个作用于Servlet生命周期的注解,实现Bean初始化之前和销毁之前的自定义操作

    @PostConstruct是Java自己的注解

    @PostConstruct该注解被用来修饰一个非静态的void()方法

    @PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次

    @PostConstruct在构造函数之后执行,init()方法之前执行

    假设类UserController有个成员变量UserService被**@Autowired**修饰,那么UserService的注入是在UserController的构造方法之后执行的。如果想在UserController对象生成时候完成某些初始化操作,而偏偏这些初始化操作又依赖于依赖注入的对象,那么就无法在构造函数中实现(ps:spring启动时初始化异常),例如:

    @Component
    public class UserController {
      @Autowired
      private UserService userService;
     
      public UserController() {
        // 调用userService的自定义初始化方法,此时userService为null,报错
        userService.userServiceInit();
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    可以使用@PostConstruct注解来完成初始化,@PostConstruct注解的方法将会在UserService注入完成后被自动调用。

    @Component
    public class UserController {
      @Autowired
      private UserService userService;
     
      public UserController() {
      }
     
      // 初始化方法
      @PostConstruct
      public void init(){
        userService.userServiceInit();
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    **总结:**类初始化调用顺序:构造方法Constructor > @Autowired > @PostConstruct

    3、InitializingBean接口

    InitializingBean是Spring提供的拓展性接口,InitializingBean接口为bean提供了属性初始化后的处理方法,它只有一个afterPropertiesSet方法,凡是继承该接口的类,在bean的属性初始化后都会执行该方法。

    除了采用注解完成初始化,也可以通过实现InitializingBean完成类的初始化

    @Component
    public class UserController {
    
      public UserController() {
      }
     
      // 初始化方法
      @PostConstruct
      public void init(){
        userService.userServiceInit();
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    比较常见的如SqlSessionFactoryBean,它就是通过实现InitializingBean完成初始化的。

    @Override
    public void afterPropertiesSet() throws Exception {
     // buildSqlSessionFactory()是完成初始化的核心方法,必须在构造方法调用后执行
     this.sqlSessionFactory = buildSqlSessionFactory(); 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4、@Bean的initMethod属性

    initMethod属性通过bean标签中的initMethod来配置实例化之后的初始化方法的

    @Component
    public class UserController {
    
      public UserController() {
      }
     
      public void init(){
        userService.userServiceInit();
      }
      
      // 初始化指向init()方法
      @Bean(initMethod = "init")
      public UserController test() {
            return new UserController();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    5、三种方式执行顺序

    通过启动日志我们可以看出执行顺序优先级:构造方法 > postConstruct >afterPropertiesSet > init方法

    public class MyInitializingBean implements InitializingBean {
    
        public MyInitializingBean() {
            System.out.println("我是MyInitializingBean构造方法执行...");
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("我是afterPropertiesSet方法执行...");
        }
    
        @PostConstruct
        public void postConstruct() {
            System.out.println("我是postConstruct方法执行...");
        }
    
        public void init(){
            System.out.println("我是init方法执行...");
        }
    }
    
    @Configuration
    class config{
        @Bean(initMethod = "init")
        public MyInitializingBean test() {
            return new MyInitializingBean();
        }
    }
    
    
    //==================执行结果===================
    /**
    我是MyInitializingBean构造方法执行...
    我是postConstruct方法执行...
    我是afterPropertiesSet方法执行...
    我是init方法执行...
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    6、总结

    • Spring为bean提供了两种初始化bean的方式,实现InitializingBean接口,实现afterPropertiesSet方法,或者在配置文件中通过init-method指定,两种方式可以同时使用。

    • 实现InitializingBean接口是直接调用afterPropertiesSet方法,比通过反射调用init-method指定的方法效率要高一点,但是init-method方式消除了对spring的依赖。

    • 如果调用afterPropertiesSet方法时出错,则不调用init-method指定的方法。

  • 相关阅读:
    《A Hierarchical Framework for Relation Extraction with Reinforcement Learning》论文阅读笔记
    Java中的SPI原理浅谈
    2023中国传媒产业发展报告
    每天学习python30分钟(第二天)
    centos7 装机遇到的问题
    React.lazy与Suspence实现延迟加载
    杰理AD14N/AD15N---Timer定时器问题
    物联网协议基础知识
    百度松果菁英班OJ【连载】
    C语言多线程编程 semaphore 信号量(信号灯)是什么?如何使用?
  • 原文地址:https://blog.csdn.net/lemon_TT/article/details/126063477