Spring中的Bean的生命周期流程

Spring中的Bean的生命周期流程

一、生命周期

Bean的完整生命周期图如下

fbe424a3-c67a-356d-bfec-be8c030ec0a6

1.1 容器启动时

BeanFactoryPostProcessor->postProcessBeanFactory() ;

1.2 实例化之后调用

InstantiationAwareBeanPostProcessor ->postProcessPropertyValues()

1.3 Bean初始化时

  1. 属性注入(setter)
  2. BeanNameAware ->setBeanName()
  3. BeanFactoryAware->setBeanFactory()
  4. ApplicationContextAware->setApplicationContext()
  5. BeanPostProcessor ->postProcessBeforeInitialization()
  6. InitializingBean->afterPropertiesSet()
  7. init-method属性
  8. BeanPostProcessor->postProcessAfterInitialization()
  9. DiposibleBean->destory()
  10. destroy-method属性

二、分类

对于BeanFactoryAware和BeanNameAware接口,第一个接口让bean感知容器(即BeanFactory实例,从而以此获取该容器配置的其他bean对象),而后者让bean获得配置文件中对应的配置名称。在一般情况下用户不需要关心这两个接口。如果bean希望获得容器中的其他bean,可以通过属性注入的方式引用这些bean。如果bean希望在运行期获知在配置文件中的Bean名称,可以简单的将名称作为属性注入

综上所述,我们认为除非编写一个基于spring之上的扩展框架插件或者子项目之类的东西,否则用户完全可以抛开以上4个bean生命周期的接口类

但BeanPostProcessor接口却不一样,它不要求bean去继承它,它可以完全像插件一样注册到spring容器中,为容器提供额外的功能。spring充分利用了BeanPostProcessor对bean进行加工处理(SpringAOP以此为基础)

Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:

2.1 Bean自身的方法

这个包括了Bean本身调用的方法和通过配置文件中的init-method和destroy-method指定的方法

2.2 Bean级生命周期接口方法

这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法

2.3 容器级生命周期接口方法

这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。

2.4 工厂后处理器接口方法

这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器  接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。

三、示例

我们用一个简单的Spring Bean来演示一下Spring Bean的生命周期。

3.1 定义一个Bean

首先是一个简单的Spring Bean,调用Bean自身的方法和Bean级生命周期接口方法,

为了方便演示,它实现了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这4个接口,

同时有2个方法,对应配置文件中的init-method和destroy-method。如下

package com.github.sadlay.spring.core.model;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * Knight骑士的model
 *
 * @Author: lay
 * @Date: Created in 9:42 2019/8/13
 * @Modified By:IntelliJ IDEA
 */

public class Knight  implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {
    private String name;
    private String sex;
    private String level;

    public Knight(String name, String sex) {
        System.out.println("【构造器】调用Knight的构造器实例化");
        this.name = name;
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("【注入属性】注入属性name");
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        System.out.println("【注入属性】注入属性sex");
        this.sex = sex;
    }

    public String getLevel() {
        return level;
    }

    public void setLevel(String level) {
        this.level = level;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()");
    }

    @Override
    public void setBeanName(String s) {
        System.out.println("【BeanNameAware接口】调用BeanNameAware.setBeanName()");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("【DiposibleBean接口】调用DiposibleBean.destory()");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("【InitializingBean接口】调用InitializingBean.afterPropertiesSet()");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("【ApplicationContextAware】ApplicationContextAware.setApplicationContext()");
    }

    public void initMethod(){
        System.out.println("【init-method】调用<bean>的init-method属性指定的初始化方法");
    }

    public void destroyMethod(){
        System.out.println("【destroy-method】调用<bean>的destroy-method属性指定的初始化方法");
    }

    @Override
    public String toString() {
        return "Knight{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", level='" + level + '\'' +
                '}';
    }
}

3.2 BeanPostProcessor接口

package com.github.sadlay.spring.core.cycle;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * BeanPostProcessor
 *
 * BeanPostProcessor接口包括2个方法postProcessAfterInitialization和postProcessBeforeInitialization,这两个方法的第一个参数都是要处理的Bean对象,第二个参数都是Bean的name。返回值也都是要处理的Bean对象。这里要注意。
 *
 * @Author: lay
 * @Date: Created in 10:43 2019/8/13
 * @Modified By:IntelliJ IDEA
 */
public class MyBeanPostProcessor implements BeanPostProcessor {

    public MyBeanPostProcessor() {
        super();
        System.out.println("这是【BeanPostProcessor】实现类构造器!!");
    }

    @Override
    public Object postProcessAfterInitialization(Object arg0, String arg1) throws BeansException {
        System.out.println("【BeanPostProcessor】接口方法postProcessAfterInitialization对属性进行更改!");
        return arg0;
    }

    @Override
    public Object postProcessBeforeInitialization(Object arg0, String arg1) throws BeansException {
        System.out.println("【BeanPostProcessor】接口方法postProcessBeforeInitialization对属性进行更改!");
        return arg0;
    }
}

如上,BeanPostProcessor接口包括2个方法postProcessAfterInitialization和postProcessBeforeInitialization,这两个方法的第一个参数都是要处理的Bean对象,第二个参数都是Bean的name。返回值也都是要处理的Bean对象。这里要注意。

3.3 InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor 接口本质是BeanPostProcessor的子接口,一般我们继承Spring为其提供的适配器类InstantiationAwareBeanPostProcessorAdapter来使用它,如下:

package springBeanTest;  
   
 import java.beans.PropertyDescriptor;    
 import org.springframework.beans.BeansException;  
 import org.springframework.beans.PropertyValues;  
 import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;  
   
 public class MyInstantiationAwareBeanPostProcessor extends  
        InstantiationAwareBeanPostProcessorAdapter {  
  
    public MyInstantiationAwareBeanPostProcessor() {  
        super();  
        System.out.println("这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!");  
    }  
  
    // 接口方法、实例化Bean之前调用  
    @Override  
    public Object postProcessBeforeInstantiation(Class beanClass,  
            String beanName) throws BeansException {  
       
        System.out.println("InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法");  
        return null;  
    }  
  
    // 接口方法、实例化Bean之后调用  
    @Override  
    public Object postProcessAfterInitialization(Object bean, String beanName)  
            throws BeansException {  
        System.out.println("InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法");  
        return bean;  
    }  
  
    // 接口方法、设置某个属性时调用  
    @Override  
    public PropertyValues postProcessPropertyValues(PropertyValues pvs,  
            PropertyDescriptor[] pds, Object bean, String beanName)  
            throws BeansException {  
        System.out.println("InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法");  
        return pvs;  
    }  
}  

这个有3个方法,其中第二个方法postProcessAfterInitialization就是重写了BeanPostProcessor的方法。第三个方法postProcessPropertyValues用来操作属性,返回值也应该是PropertyValues对象。

3.4 BeanFactoryPostProcessor

演示工厂后处理器接口方法,如下:

package springBeanTest;  
   
 import org.springframework.beans.BeansException;  
 import org.springframework.beans.factory.config.BeanDefinition;  
 import org.springframework.beans.factory.config.BeanFactoryPostProcessor;  
 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;  
   
 public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {  
   
    public MyBeanFactoryPostProcessor() {  
        super();  
        System.out.println("这是BeanFactoryPostProcessor实现类构造器!!");  
    }  
  
    @Override  
    public void postProcessBeanFactory(ConfigurableListableBeanFactory arg)  
            throws BeansException {  
        System.out  
                .println("BeanFactoryPostProcessor调用postProcessBeanFactory方法");  
        BeanDefinition bd = arg.getBeanDefinition("person");  
        bd.getPropertyValues().addPropertyValue("phone", "");  
    }   
}  

3.5 配置文件

使用javaConfig的形式注册bean

package com.github.sadlay.spring.core.config;

import com.github.sadlay.spring.core.cycle.MyBeanFactoryPostProcessor;
import com.github.sadlay.spring.core.cycle.MyBeanPostProcessor;
import com.github.sadlay.spring.core.cycle.MyInstantiationAwareBeanPostProcessor;
import com.github.sadlay.spring.core.model.Knight;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Bean配置
 *
 * @Author: lay
 * @Date: Created in 9:42 2019/8/13
 * @Modified By:IntelliJ IDEA
 */
@Configuration
public class BeanConfig {

    @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
    public Knight knight() {
        return new Knight("lay", "男");
    }

    @Bean
    public BeanPostProcessor myBeanPostProcessor() {
        return new MyBeanPostProcessor();
    }

    @Bean
    public InstantiationAwareBeanPostProcessorAdapter myInstantiationAwareBeanPostProcessor() {
        return new MyInstantiationAwareBeanPostProcessor();
    }

    @Bean
    public BeanFactoryPostProcessor myBeanFactoryPostProcessor() {
        return new MyBeanFactoryPostProcessor();
    }
}

3.6 测试

package com.github.sadlay.spring.core;

import com.github.sadlay.spring.core.model.Knight;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * 主启动类
 *
 * @Author: lay
 * @Date: Created in 9:38 2019/8/13
 * @Modified By:IntelliJ IDEA
 */
@Configuration
@ComponentScan("com.github.sadlay")
public class SpringCoreApplication {

    public static void main(String[] args) {
        System.out.println("现在开始初始化容器");
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringCoreApplication.class);
        System.out.println("容器初始化成功");
        Knight bean = context.getBean(Knight.class);
        System.out.println(bean.toString());
        System.out.println("现在开始关闭容器!");
        ((AnnotationConfigApplicationContext) context).close();
    }
}

ApplicationContext context = new AnnotationConfigApplicationContext(SpringCoreApplication.class);
System.out.println(“容器初始化成功”);
Knight bean = context.getBean(Knight.class);
System.out.println(bean.toString());
System.out.println(“现在开始关闭容器!”);
((AnnotationConfigApplicationContext) context).close();
}
}








  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Bean的生命周期可以分为以下过程:实例化、属性注入、BeanPostProcessor前置处理、初始化、BeanPostProcessor后置处理、销毁。 首先,在容器初始化时,Spring会读取配置文件或注解等方式,找到并实例化Bean。Bean的实例化可以通过构造器进行,也可以通过工厂方法进行。当容器调用构造器或者工厂方法时,Bean就会被实例化,但此时Bean还未被初始化。 其次,在实例化后,Spring会将Bean的属性注入。属性注入的方式有两种:setter注入和构造器注入。如果选择setter注入,则Spring会通过反射机制将属性值注入到Bean。如果是构造器注入,则Spring容器会找到匹配的构造器,并将属性值注入到Bean。 接下来,对Bean进行初始化。在初始化过程Spring框架会使用各种回调方法,以达到对Bean的加工和改造的目的。Bean的初始化可以通过实现接口来完成,也可以通过注解等方式完成。其最常用的是InitializingBean接口和@PostConstruct注解。 初始化完成后,Spring会进行BeanPostProcessor前置处理。在该处理过程Spring会检查是否有实现BeanPostProcessor接口的类,如果有则会调用其两个方法postProcessBeforeInitialization(…)和postProcessAfterInitialization(…),分别在Bean的初始化前和初始化后进行处理。 最后,当Bean不再被使用时,Spring会调用销毁方法进行销毁操作。Bean的销毁可以通过实现DisposableBean接口完成,也可以通过注解等方式完成。其最常用的是DisposableBean接口和@PreDestroy注解。 综上所述,Spring Bean的生命周期流程包括:实例化、属性注入、BeanPostProcessor前置处理、初始化、BeanPostProcessor后置处理、销毁。对于每个Bean,Spring会按照以上流程进行处理,确保Bean能够达到预期的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值