BeanFactory 的生命周期

由于Bean的生命周期经历的阶段比较多,下面将通过图形化的方式描述:

通过 getBean() 调用 某个Bean

Bean 生命周期

具体过程如下:
(1),当调用者通过getBean(beanName) 请求某一个Bean 时,如果容器注册了 org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor 接口,则在实例化Bean 之前,将调用 postProcessBeforeInstantiation()方法
(2),根据配置情况调用Bean构造函数 或工厂方法实例化Bean
(3),如果容器注册了InstantiationAwareBeanPostProcessor 接口,那么在实例化Bean 之后,调用该接口 的postProcessAfterInstantiation()方法,可在这里对已经实例化的Bean 进行一些操作
(4),如果Bean配置了属性信息,那么容器在这一步着手将配置值设置到Bean 对应的属性中去,在设置每个属性值之前都会调用 InstantiationAwareBeanPostProcessor 接口的 postProcessPropertyValues 方法
(5),调用Bean 的属性设置方法 设置属性值
(6),如果Bean 实现了 BeanNameAware 接口 则将调用 setBeanName 接口方法,将配置文件中该Bean 的对应名称设置到Bean 中去
(7),如果Bean 实现了 BeanFactoryAware 接口 则将调用 setBeanFactory 接口方法,将BeanFactory容器实例设置到Bean 中去
(8),如果BeanFactory 装配了 org.springframework.beans.factory.config.BeanPostProcessor 后处理 ,则将调用postProcessBeforeInitialization(Object bean, String beanName) 方法 对Bean 进行加工操作,其中,入参Bean 是当前操作的Bean,而BeanName 是当前 Bean 的 配置名,返回对象加工后的Bean。
(9),如果Bean实现了 InitializingBean 接口,则将调用接口的afterPropertiesSet 方法
(10),如果在applicationContext 配置文件中通过init-method属性指定了初始化方法,则将执行这个方法
(11),如果BeanFactory 装配了 org.springframework.beans.factory.config.BeanPostProcessor 后处理 ,则将调用postProcessAfterInitialization(Object bean, String beanName) 方法 这个方法在此时调用,容器再次获得了对Bean 的加工机会
(12),如果在<Bean> 中指定了作用范围 scope = "prototype" 则将Bean返回给调用者 有调用者 管理 Bean 的生命周期,如果 scope = "singleton" ,则将Bean 放入 IOC容器的 缓存池中,由Spring 管理Bean 的生命周期
(13),如果Bean 实现了 DisposableBean 接口则将调用接口的 destroy()方法
(14),如果<Bean> 的 destory-method 属性指定了Bean 的销毁方法,那么Spring 将执行 Bean 的这个方法,完成Bean的资源释放的工作

代码验证:

public class Car implements BeanFactoryAware,BeanNameAware,InitializingBean,DisposableBean{
    
    private String brand;
    
    private String color;
    
    private Integer maxSpeed;
    
    private String beanName;
    
    private BeanFactory beanFactory;
    
    public Car(){
        System.out.println("Car() 构造器调用");
    }
    
    @Override
    public void destroy() throws Exception {
        System.out.println("调用 DisposableBean destroy 方法");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("调用 InitializingBean afterPropertiesSet 方法");
    }

    @Override
    public void setBeanName(String beanName) {
        System.out.println("调用 BeanNameAware setBeanName 方法");
        this.beanName = beanName;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("调用 BeanFactoryAware setBeanFactory 方法");
        this.beanFactory = beanFactory;
    }
    
    public void introduce(){
        System.out.println("Car[brand : "+brand+",color:"+color+",maxSpeed:"+maxSpeed+"]");
    }
    
    @Override
    public String toString() {
        return "Car[brand : "+brand+",color:"+color+",maxSpeed:"+maxSpeed+"]";
    }
    
    public void myInit(){
        System.out.println("调用 init-method 指定的myInit 方法");
    }
    
    public void myDestroy(){
        System.out.println("调用 init-method 指定的myDestroy 方法");
    }
    
    //=====================================//
    
    public String getBrand() {
        return brand;
    }

    public String getColor() {
        return color;
    }

    public Integer getMaxSpeed() {
        return maxSpeed;
    }
    
    public BeanFactory getBeanFactory() {
        return beanFactory;
    }

    public String getBeanName() {
        return beanName;
    }

    public void setBrand(String brand) {
        System.out.println("调用 setBrand 设置 属性");
        this.brand = brand;
    }

    public void setColor(String color) {
        System.out.println("调用 setColor 设置 属性");
        this.color = color;
    }

    public void setMaxSpeed(Integer maxSpeed) {
        System.out.println("调用 setMaxSpeed 设置 属性");
        this.maxSpeed = maxSpeed;
    }
}
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter{
    
    public Object postProcessBeforeInstantiation(Class<?> beanClass,String beanName) throws BeansException {
        if("car".equals(beanName)){
            System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation 方法");
        }
        return super.postProcessBeforeInstantiation(beanClass, beanName);
    }
    
    public boolean postProcessAfterInstantiation(Object bean, String beanName)throws BeansException {
        if("car".equals(beanName)){
            System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation 方法");
        }
        return super.postProcessAfterInstantiation(bean, beanName);
    }
    
    public PropertyValues postProcessPropertyValues(PropertyValues pvs,PropertyDescriptor[] pds, Object bean, String beanName)
            throws BeansException {
        if("car".equals(beanName)){
            System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessPropertyValues 方法");
        }
        return super.postProcessPropertyValues(pvs, pds, bean, beanName);
    }
}
public class MyBeanPostProcess implements BeanPostProcessor{

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)throws BeansException {
        if("car".equals(beanName)){
            System.out.println("调用MyBeanPostProcess.postProcessBeforeInitialization 方法");
            Car car = (Car)bean;
            if(car.getColor() == null){
                car.setColor("黑色");
            }
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)throws BeansException {
        if("car".equals(beanName)){
            System.out.println("调用 MyBeanPostProcess.postProcessAfterInitialization 方法");
            Car car = (Car)bean;
            if(car.getMaxSpeed() > 100){
                car.setMaxSpeed(100);
            }
        }
        return bean;
    }

}
public class BeanLifeCycle {
    private static void beanLifeCycleInFactory(){
        
        //配置文件并启动容器
        Resource resource = new ClassPathResource("applicationContext.xml");
        BeanFactory factory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader((DefaultListableBeanFactory)factory);
        reader.loadBeanDefinitions(resource);
        
        //向容器中注册 MyBeanPostProcess 后处理器
        ((DefaultListableBeanFactory)factory).addBeanPostProcessor(new MyBeanPostProcess());
        
        //向容器中注册 MyInstantiationAwareBeanPostProcessor 后处理器
        ((DefaultListableBeanFactory)factory).addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());
        
        //从容器中获取bean 将触发容器中实例化 bean 这将引发Bean 生命周期方法的调用
        Car car1 = factory.getBean(Car.class);
        
        car1.introduce();
        
        //第二次获取bean  直接从缓存中读取
        Car car2 = factory.getBean(Car.class);
        
        //查看 car1 和 car2是否是同一个引用
        System.out.println(car1 == car2);
        
        //关闭容器
        ((DefaultListableBeanFactory)factory).destroySingletons();
        
        //((ClassPathXmlApplicationContext)ctx).destroy();
    }
    
    public static void main(String[] args) {
        BeanLifeCycle.beanLifeCycleInFactory();
    }
}

输出的结果:

MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation 方法
Car() 构造器调用
MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation 方法
MyInstantiationAwareBeanPostProcessor.postProcessPropertyValues 方法
调用 setBrand 设置 属性
调用 setMaxSpeed 设置 属性
调用 BeanNameAware setBeanName 方法
调用 BeanFactoryAware setBeanFactory 方法
调用MyBeanPostProcess.postProcessBeforeInitialization 方法
调用 setColor 设置 属性
调用 InitializingBean afterPropertiesSet 方法
调用 init-method 指定的myInit 方法
调用 MyBeanPostProcess.postProcessAfterInitialization 方法
调用 setMaxSpeed 设置 属性
Car[brand : BMW,color:黑色,maxSpeed:100]
true
调用 DisposableBean destroy 方法
调用 init-method 指定的myDestroy 方法
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • Spring容器高层视图 Spring 启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相...
    Theriseof阅读 2,795评论 1 24
  • 什么是Spring Spring是一个开源的Java EE开发框架。Spring框架的核心功能可以应用在任何Jav...
    jemmm阅读 16,438评论 1 133
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,732评论 6 342
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,594评论 18 139
  • 互联网时代,各行各业都在朝移动端方向发展,好像只要手机下载APP,就能”一键“搞定,”智能“解决。当“语音翻译”、...
    科燕路由阅读 139评论 0 0