您的位置:

深入理解Spring Boot Bean生命周期

Spring Boot是一种基于Spring框架的快速应用程序开发工具,它旨在使Spring应用程序的开发变得更简单、更快速,但对于新手来说可能仍然是一种挑战,尤其是对于生命周期背后的实现细节。本文将从多个方面详细阐述Spring Boot的Bean生命周期,帮助开发者更好地理解和使用Spring Boot。

一、Bean的实例化

当Bean被加载到容器中时,需要根据配置信息创建Bean的实例对象,这个过程叫做Bean的实例化。Spring提供了两种方式来创建Bean的实例:

  1. 使用默认构造函数:Spring通过无参构造函数来创建Bean实例,这需要保证该Bean类中存在无参构造函数。
  2. 工厂方法:对于需要进行一些初始化或者创建的逻辑处理的Bean,Spring也提供了工厂方法。Developer可以在Bean类中编写返回对象的静态方法,由Spring容器调用所返回的实例。

下面是使用默认构造函数和工厂方法分别实例化Bean的实现示例:

public class User {
    private String name;
    private int age;
    
    // 默认构造函数
    public User() {}

    // 带参数的构造函数
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 工厂方法
    public static User createUser() {
        return new User("Tom", 25);
    }

    // getter和setter方法省略
}

@Configuration
public class AppConfig {

    // 通过@Bean注解,将User作为一个Bean注入到Spring容器中
    @Bean(name = "user")
    public User initUserByDefaultConstructor() {
        return new User();
    }

    @Bean(name = "user2")
    public User initUserByStaticFactoryMethod() {
        return User.createUser();
    }
}

二、Bean的初始化

当Bean实例创建成功后,需要对该实例执行一些初始化的工作。Spring提供了两个接口来支持Bean初始化:

  1. InitializingBean:该接口提供了一个afterPropertiesSet()方法,该方法在Bean实例化完成后回调。InitializingBean接口可以让开发者在Bean实例化完成后进行一些初始化的操作。
  2. 配置init方法:开发者可以在Bean类中配置init方法,该方法将在Bean实例化完成后被容器调用。开发者应该考虑使用init方法进行一些初始化的操作,这样更加灵活。

下面是使用InitializingBean接口和配置init方法分别实例化Bean的实现示例:

public class User implements InitializingBean {
    private String name;
    private int age;

    public User() {}

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static User createUser() {
        return new User("Tom", 25);
    }

    public void afterPropertiesSet() {
        System.out.println("--------------Bean初始化完成-------------");
    }

    public void initMethod() {
        System.out.println("-------------通过initMethod()方法初始化Bean----------------");
    }

    // getter和setter方法省略
}

@Configuration
public class AppConfig {

    @Bean(name = "user")
    public User initUserByDefaultConstructor() {
        User user = new User();
        return user;
    }

    @Bean(name = "user2")
    public User initUserByStaticFactoryMethod() {
        User user = User.createUser();
        return user;
    }

    @Bean(name = "user3", initMethod = "initMethod")
    public User initUserByInitMethod() {
        User user = new User("Tom", 25);
        return user;
    }
}

三、Bean的依赖注入

依赖注入是Spring框架的核心特性之一。依赖注入的目的是将Bean之间的依赖关系从程序代码中解耦出来,让开发者可以更加灵活的编写程序。

Spring支持三种方式进行依赖注入:

  1. 构造函数依赖注入:通过Bean类中的构造函数实现依赖注入。
  2. 属性Setter方法依赖注入:通过Bean类中的setProperty()方法实现依赖注入。
  3. 注解依赖注入:通过注解方式自动装配实现依赖注入。

下面是三种方式实现依赖注入的示例:

public class User {
    private String name;
    private int age;

    public User() {}

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void initMethod() {
        System.out.println("----------------依赖注入完成-----------");
    }

    // getter和setter方法
}

public class ProductService {
    private User user;

    public ProductService(User user) {
        this.user = user;
    }

    public void validate() {
        System.out.println("User's Name:" + user.getName() + " User's Age:" + user.getAge());
    }
}

@Configuration
public class AppConfig {

    @Bean(name = "user")
    public User initUser() {
        User user = new User("Tom", 25);
        return user;
    }

    /**
     * 构造方法注入
     * @param user
     * @return
     */
    @Bean(name = "productService")
    public ProductService initProductServiceByConstructor(User user) {
        return new ProductService(user);
    }

    /**
     * setter方法注入
     * @param user
     * @return
     */
    @Bean(name = "productService2")
    public ProductService initProductServiceBySetMethod(User user) {
        ProductService productService = new ProductService();
        productService.setUser(user);
        return productService;
    }

    /**
     * 注解注入
     * @return
     */
    @Bean(name = "productService3")
    public ProductService initProductService() {
        return new ProductService(new User("Tomson", 26));
    }
}

四、Bean的销毁

在Bean实例不再需要,容器需要将其从容器中清除前,需要执行销毁Bean的相关操作。Spring提供了两个方法来支持Bean的销毁操作:

  1. DisposableBean:该接口提供了一个destroy()方法,该方法在Bean销毁之前将被调用。
  2. 配置destroy方法:在Bean类中可以配置destroy方法,该方法将在Bean销毁之前被调用。

下面是DisposableBean方法和配置destroy方法分别实现Bean销毁操作的示例:

public class User implements InitializingBean, DisposableBean {
    private String name;
    private int age;

    public User() {}

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void setProperty(String name, int age){
        this.name = name;
        this.age = age;
    }

    public void afterPropertiesSet() {
        System.out.println("--------------Bean初始化完成-------------");
    }

    public void initMethod() {
        System.out.println("-------------通过init-method()方法初始化Bean----------------");
    }

    public void destroy() throws Exception {
        System.out.println("--------------销毁Bean-------------");
    }

    public void destroyMethod() {
        System.out.println("----------------通过destroy-method()方法销毁Bean-----------");
    }

    // getter、setter方法
}

@Configuration
public class AppConfig {

    @Bean(name = "user", initMethod = "initMethod", destroyMethod = "destroyMethod")
    public User initUser() {
        User user = new User();
        user.setProperty("Tom", 25);
        return user;
    }

    /**
     * 通过DisposableBean实现销毁操作
     * @return
     */
    @Bean(name = "user2")
    public User initUser2() {
        User user = new User();
        user.setProperty("Tomson", 26);
        return user;
    }

    @Bean(name = "productService2")
    public ProductService initProductServiceBySetMethod(User user) {
        ProductService productService = new ProductService();
        productService.setUser(user);
        return productService;
    }
}

五、小结

通过以上介绍,我们可以看到Spring Boot Bean的生命周期包括了Bean实例化、Bean初始化、依赖注入以及Bean销毁这四个方面。Spring Boot提供了多种方式来支持Bean生命周期的控制,在使用的时候,开发者应该根据实际需求选择合适的方式,并按照Spring Boot的规则来编写代码。