Spring5源码分析------bean的生命周期(二)

代码地址
spring02
觉得博主还可以给个Star

Spring Bean的生命周期

  1. 如何判断Bean初始化了
    初始化:指的是对象已经创建并且里面所有的set已经全部执行完毕
    在@Bean中有着initMethod,destoryMethod属性,他们代表着bean被初始化和销毁
    具体用法:
    UserEntity.java
package com.entity;


public class UserEntity {
    
    

    public UserEntity(){
    
    
        System.out.println("UserEntity无参构造...");
    }

    private void initMsg() {
    
    
        System.out.println("UserEntity initMsg");
    }

    private void destroyMsg() {
    
    
        System.out.println("UserEntity destroyMsg");
    }
}

MyConfig.java

@Configuration
@ComponentScan("com.entity")
public class MyConfig {
    
    

    @Bean(initMethod = "initMsg",destroyMethod = "destroyMsg")
    public UserEntity userEntity(){
    
    
        return new UserEntity();
    }
}

Application.java

import com.config.MyConfig;
import com.entity.UserEntity;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Application {
    
    
    public static void main(String[] args) {
    
    
//        ApplicationContext
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        UserEntity userEntity = annotationConfigApplicationContext.getBean("userEntity", UserEntity.class);
    }
}

运行结果:
在这里插入图片描述
我们会发现"UserEntity destroyMsg"并未被打印出来,那是因为容器并未被销毁,所以我们可以自己关闭容器,清除里面的bean
Application.java

import com.config.MyConfig;
import com.entity.UserEntity;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Application {
    
    
    public static void main(String[] args) {
    
    
//        ApplicationContext
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        UserEntity userEntity = annotationConfigApplicationContext.getBean("userEntity", UserEntity.class);
        annotationConfigApplicationContext.close();
    }
}

在这里插入图片描述
其实判断的方法还有很多种,比如

  1. 实现接口InitializingBean, DisposableBean
    创建BookEntity.java
package com.entity;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class BookEntity implements InitializingBean, DisposableBean {
    
    
    @Override
    public void destroy() throws Exception {
    
    
        System.out.println("BookEntity 销毁前执行");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
    
    
        System.out.println("BookEntity实例化完成");
    }
}

在这里插入图片描述
2. JSR250
创建PayEntity.java

package com.entity;

import org.springframework.stereotype.Component;

@Component
public class PayEntity {
    
    

    @PreDestroy
    public void destroy(){
    
    
        System.out.println("BookEntity 销毁前执行");
    }

    @PostConstruct
    public void afterPropertiesSet(){
    
    
        System.out.println("BookEntity实例化完成");
    }
}

弄清楚了怎么判断bean的初始化,我们先来看源码
在这里插入图片描述
在这里插入图片描述
try中倒数第二个方法
在这里插入图片描述
可以看到上面的注释,差不多意思为初始化所有的单例在这里插入图片描述
初始化所有的单例,非懒加载
在这里插入图片描述
获取所有的beanName,并使用RootBeanDefinition注入
在这里插入图片描述
在这里插入图片描述
上面几步为查询对象是否有初始化过,没有的话就创建到IOC容器中
在这里插入图片描述
创建对象,判断对象如果是单例的情况下调用该方法
在这里插入图片描述
创建IOC对象
在这里插入图片描述
通过反射实例化bean

在这里插入图片描述
populateBean(beanName, mbd, instanceWrapper);方法是给对象set方法属性填充
initializeBean执行初始化方法(也可以自定义初始化方法)
在这里插入图片描述
判断bean的类型是否Aware相关依赖,如果存在则回调方法
好了,重点来了
在这里插入图片描述

  1. 如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 方法传入当前 Bean 的 id 值。
  2. 如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前工厂实例的引用。
  3. 如果 Bean 实现了 ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 方法传入当前 ApplicationContext 实例的引用。
    第三点就完美解决了我们在过滤器当中,不能使用注解形式获取bean的问题,我们可以直接通过上下文获取bean。

好了,现在返回到
在这里插入图片描述
初始化方法之前执行处理(增强)
在这里插入图片描述
2调用自定义init方法(使用java反射技术,此方法在无参构造函数后执行)
3在初始化方法之后调用(增强)

我们会发现1和3他们有一个单词的差别,一个前一个后,也就是作用于自定义Init方法前后执行,在他们中间2也就是自定义Init方法
之后也就是调用,销毁了。然后我们也就总结出了,bean生命周期的周期图
在这里插入图片描述
语言描述:
Bean 生命周期的整个执行过程描述如下。

1)根据配置情况调用 Bean 构造方法或工厂方法实例化 Bean。

2)利用依赖注入完成 Bean 中所有属性值的配置注入。

3)如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 方法传入当前 Bean 的 id 值。

4)如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前工厂实例的引用。

5)如果 Bean 实现了 ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 方法传入当前 ApplicationContext 实例的引用。

6)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的预初始化方法 postProcessBeforeInitialzation() 对 Bean 进行加工操作,此处非常重要,Spring 的 AOP 就是利用它实现的。

7)如果 Bean 实现了 InitializingBean 接口,则 Spring 将调用 afterPropertiesSet() 方法。

8)如果在配置文件中通过 init-method 属性指定了初始化方法,则调用该初始化方法。

9)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的初始化方法 postProcessAfterInitialization()。此时,Bean 已经可以被应用系统使用了。

10)如果在 中指定了该 Bean 的作用范围为 scope=“singleton”,则将该 Bean 放入 Spring IoC 的缓存池中,将触发 Spring 对该 Bean 的生命周期管理;如果在 中指定了该 Bean 的作用范围为 scope=“prototype”,则将该 Bean 交给调用者,调用者管理该 Bean 的生命周期,Spring 不再管理该 Bean。

11)如果 Bean 实现了 DisposableBean 接口,则 Spring 会调用 destory() 方法将 Spring 中的 Bean 销毁;如果在配置文件中通过 destory-method 属性指定了 Bean 的销毁方法,则 Spring 将调用该方法对 Bean 进行销毁。
直至,还有一个重要的BeanPostProcessors,其实内部的重要方法我们已经见过
在这里插入图片描述
两个处理器,当然,它远远没有那么简单,后续揭晓

猜你喜欢

转载自blog.csdn.net/weixin_43911969/article/details/114003861