浅析Spring生命周期-LMLPHP

前言

Spring框架是一个非常流行的Java企业级应用程序框架,已经成为许多生产环境中的首选技术。它提供了一种便捷的方法来帮助开发人员构建可扩展和模块化的企业级应用程序。在Spring框架中,Bean生命周期是非常重要的一部分,它负责Bean的创建和销毁。

一个完整的Spring的Bean的生命周期

Spring框架中Bean的完整生命周期包括:

  1. 实例化Bean
  2. 设置对象属性
  3. 对Bean执行用户定义的初始化方法
  4. Bean可用
  5. 关闭容器

浅析Spring生命周期-LMLPHP

实例化Bean

在 Spring 中,实例化 Bean 主要有两种方式:使用构造函数实例化和使用静态工厂方法实例化。

构造函数实例化是使用类的构造函数创建 Bean 对象的方式。在 Spring 配置文件中,可以通过 元素的 constructor-arg 子元素来指定 Bean 的构造函数参数。

静态工厂方法实例化是指在 BeanFactory 创建 Bean 实例时,调用静态工厂方法创建 Bean 对象。在 Spring 配置文件中,可以通过 元素的 class 属性和 factory-method 属性来指定 Bean 工厂类和工厂方法。

需要注意的是,在 Spring 中,Bean 实例化后并不直接进入使用状态,而是存放在 BeanFactory 中,等待被其他 Bean 使用。如果没有配置 Bean 的作用域为 singleton,则每次使用 Bean 时都会创建一个新的 Bean 实例。

在Bean实例化的时候,有几个比较重要的接口,我们可以看下。

1. BeanFactoryPostProcessor

BeanFactoryPostProcessor它能够让开发人员在Bean工厂创建Bean之前对其进行配置或修改,同时还能在Bean实例化之前进行一些定制化操作。通过BeanFactoryPostProcessor接口,开发人员可以访问到Spring容器内的BeanFactory,从而改变Bean的配置信息,例如将某个Bean的scope从singleton改变为prototype。

2. BeanPostProcessor

当我们在创建Bean的时候,Spring框架会按照Bean的生命周期方法先后顺序执行相应的方法。其中BeanPostProcessor接口定义了两个方法,beforeInitialization和afterInitialization,用于在Bean初始化前和Bean初始化后进行处理。

设置对象属性

设置对象属性是Spring Bean生命周期中的一个阶段。在这个阶段,Spring框架会根据Bean的配置信息为对象设置属性并将其装配到应用程序中。

具体实现方法是在Bean的配置信息中添加属性元素,用于配置对象的属性值。例如:

<bean id="exampleBean" class="com.example.Example">
    <property name="name" value="John Doe" />
    <property name="age" value="30" />
</bean>

另外,在使用注解的方式配置Bean时,也可以使用@Autowired注解或者@Resource注解为对象的属性进行自动装配。这些注解可以根据Type或Name自动查找适配的Bean进行装配,从而减少了手动配置Bean属性的工作。例如:

@Component
public class ExampleComponent {
    @Autowired
    private ExampleBean exampleBean;

    public void doSomething() {
        // 使用exampleBean对象执行一些操作
    }
}

@Component
public class ExampleBean {
    private String name;
    private int age;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

对Bean执行用户定义的初始化方法

对Bean执行用户定义的初始化方法在Spring框架中是通过Bean的生命周期回调方法来实现的。具体步骤如下:

1. 实现InitializingBean

InitializingBean是Spring框架中一个非常重要的接口之一,定义了Bean初始化后要执行的操作。在BeanFactory完成对Bean实例的配置和添加Bean实例的前置和后置处理工作之后,Spring容器将调用InitializingBean接口的afterPropertiesSet方法进行Bean的初始化执行操作。

在Bean类中实现InitializingBean接口,该接口中定义了一个afterPropertiesSet()方法,该方法会在Bean初始化完成之后被调用。

public class MyBean implements InitializingBean {
    // ...
    @Override
    public void afterPropertiesSet() throws Exception {
        // 在这里编写Bean初始化的逻辑
        // ...
    }
    // ...
}

2. 使用@PostConstruct注解

还可以使用@PostConstruct注解,在Bean初始化完成之后执行指定的方法,例如:

public class MyBean {
    // ...
    @PostConstruct
    public void init() {
        // 在这里编写Bean初始化的逻辑
        // ...
    }
    // ...
}

3. 指定init方法

也可以在XML配置文件中指定Bean初始化时调用的方法,例如:

<bean id="myBean" class="com.example.MyBean" init-method="init"/>

其中,init-method属性指定了Bean初始化时要调用的方法名。

以上是三种常用的对Bean执行用户定义的初始化方法的实现方式,您可以根据具体情况选择其中的一种方式。
浅析Spring生命周期-LMLPHP

Bean可用

简单来说,在Spring生命周期中,Bean可用是在BeanFactory启动阶段的某个时刻被触发的,表示这个Bean已经完成了所有的初始化工作,可以被其他Bean调用和使用。在这个状态下,Bean已经处于正常运行状态,可以对外提供服务或者处理业务逻辑。

这里提供一个简单的Spring生命周期Bean可用的示例代码。首先,我们定义一个名为BeanLifeCycleDemo的类,并指定初始化和销毁方法。代码如下:

public class BeanLifeCycleDemo {
    private String message;

    public void init() {
        System.out.println("Bean is being initialized.");
        this.message = "Hello, world!";
    }

    public void destroy() {
        System.out.println("Bean is being destroyed.");
    }

    public String getMessage() {
        return this.message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

接下来,我们需要在Spring配置文件中声明这个类的Bean,并指定它的初始化和销毁方法。配置文件为beans.xml,代码如下:

<bean id="beanLifeCycleDemo" class="com.example.BeanLifeCycleDemo"
      init-method="init" destroy-method="destroy">
    <property name="message" value="Hello, world!"/>
</bean>

最后,我们创建一个测试类AppTest,并在其中测试输出Bean的信息。代码如下:

public class AppTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("beans.xml");
        BeanLifeCycleDemo bean = context.getBean("beanLifeCycleDemo", BeanLifeCycleDemo.class);
        System.out.println(bean.getMessage());
        context.close();
    }
}

通过以上示例,我们可以看到,在Spring生命周期中,Bean可用是在Bean初始化完成后被触发的。在这个状态下,我们可以对Bean进行操作,包括调用它的方法、获取它的属性等。
浅析Spring生命周期-LMLPHP

关闭容器

在 Spring 框架中,Bean 生命周期的最后一个阶段是关闭容器,即当应用程序完成运行时,应调用 ApplicationContext 的 close() 方法,以便释放所有资源和 Bean 所占用的内存。当 ApplicationContext 关闭时,它会通知 Bean,以便它们可以对关闭操作作出响应。

以下是关闭容器时 Bean 生命周期涉及的步骤:

  1. 当 BeanFactory 关闭时,将调用所有 DisposableBean 实例的 destroy() 方法。
  1. 如果 Bean 实现了 DisposableBean 接口,则调用 destroy() 方法。这个方法允许 Bean 清理任何在应用程序运行时已经初始化或记录的资源。

  2. 调用在 Bean 定义中定义的任何自定义销毁方法。自定义销毁方法可以通过指定 destroy-method 属性来定义。例如:

    <bean id="myBean" class="com.example.MyBean" destroy-method="cleanup"/>
    

    这里的 cleanup() 方法将在关闭容器时被调用。

  3. 关闭内部 bean 容器。
    如果 bean 是 ApplicationContext 的子容器,则首先关闭子容器中的 bean。然后关闭 ApplicationContext 自身,以确保所有 bean 处于已销毁状态。

需要注意的是,在应用程序关闭时,所有的资源,如数据库连接、文件句柄等,必须被有效地释放。因此,实现 destroy() 和自定义销毁方法是非常重要的。通过这些方法,可以确保 bean 释放所有的资源,并在关闭应用程序时正确地退出。

结论

Spring的Bean生命周期可以分为两个阶段:BeanFactory准备和BeanFactory启动,其中Bean创建、初始化、销毁等过程都在这个时间段内完成。在BeanFactory准备阶段,Spring容器对BeanFactory进行了初始化,包括加载配置文件、实例化Bean工厂等。在该阶段,调用了Bean Factory Post Processor(BFPP)和Bean Post Processor(BPP)等接口,对FactoryBean和普通Bean进行预处理。在BeanFactory启动阶段,Spring容器启动后会实例化所有的Bean,并根据定义的属性、依赖等设置对Bean进行初始化。在这个过程中,调用了Bean的构造函数和初始化方法,对Bean进行了依赖注入等操作,同时也触发了Bean可以使用的状态。在容器关闭时,Spring会调用Bean的销毁方法以进行一些清理工作。

06-09 13:13