spring — spring中Bean的初始化过程(一)

13 篇文章 0 订阅
1、IOC 依赖注入

IoC(Inverse of Control:控制反转)是一种设计思想,就是 将原本在程序中手动创建对象的控制权,交由Spring框架来管理。 IoC 在其他语言中也有应用,并非 Spring 特有。 IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个Map(key,value),Map 中存放的是各种对象。

2、Spring Bean

Spring beans 是那些形成Spring应用的主干的java对象。它们被Spring IOC容器初始化,装配,和管理。这些beans通过容器中配置的元数据创建。比如,以XML文件中的形式定义。
这里有三种重要的方法给Spring容器提供配置元数据。

  • XML配置文件
  • 基于注解的配置
  • 基于java的配置
    在这里插入图片描述

2.1、ClassPathXmlApplicationContext 启动构建应用上下文:
外部使用

public static void main(String[] args) {
    //根据 xml 文件内容来构建 ApplicationContext
    ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationfile.xml");
}

启动过程

public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
  private Resource[] configResources;

  // 如果已经有 ApplicationContext 并需要配置成父子关系,那么调用这个构造方法
  public ClassPathXmlApplicationContext(ApplicationContext parent) {
    super(parent);
  }
  ...
  public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
      throws BeansException {

    super(parent);
    // 根据提供的路径,处理成配置文件数组(以分号、逗号、空格、tab、换行符分割)
    setConfigLocations(configLocations);
    if (refresh) {
      refresh(); // 核心方法
    }
  }
    ...
}

refresh()初始化操作

 public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
        	// 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
            this.prepareRefresh();
            //提取配置信息,将配置文件解析成一个个 Bean 定义,注册到 BeanFactory 中,beanName-> beanDefinition 的 map
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            //设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
            this.prepareBeanFactory(beanFactory);

            try {
            	//Bean 如果实现了BeanFactoryPostProcessor此接口,那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。
                this.postProcessBeanFactory(beanFactory);
                // 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
                this.invokeBeanFactoryPostProcessors(beanFactory);
                 // 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
         		// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
        		// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
                this.registerBeanPostProcessors(beanFactory);
                // 初始化当前 ApplicationContext 的 MessageSource
                this.initMessageSource();
                // 初始化当前 ApplicationContext 的事件广播器
                this.initApplicationEventMulticaster();
                //钩子方法,初始化一些特殊的 Bean(在初始化 singleton beans 之前)
                this.onRefresh();
                // 注册事件监听器,监听器需要实现 ApplicationListener接口
                this.registerListeners();
                // 初始化所有的 singleton beans
                this.finishBeanFactoryInitialization(beanFactory);
                //广播事件,ApplicationContext 初始化完成
                this.finishRefresh();
            } catch (BeansException var9) {
           		// 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }

        }
    }
3、bean生命周期

Bean的生命周期指的就是在上面三个步骤中后置处理器BeanPostprocessor穿插执行的过程

3.1 Bean创建的三个阶段

Spring在创建一个Bean时是分为三个步骤的

  • 实例化,可以理解为new一个对象
  • 属性注入,可以理解为调用setter方法完成属性注入
  • 初始化,你可以按照Spring的规则配置一些初始化的方法(例如,@PostConstruct注解)
3.2 后置处理器

按照实现接口进行分类

  1. 直接实现了BeanPostProcessor接口
    最简单的后置处理器,也就是说直接实现了BeanPostProcessor接口,这种后置处理器只能在初始化前后执行:
public interface BeanPostProcessor {
    
 // 初始化前执行的方法
 @Nullable
 default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  return bean;
 }    
    
 // 初始化后执行的方法
 default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  return bean;
 }

}
  1. 直接实现了InstantiationAwareBeanPostProcessor接口
    在第一种后置处理的基础上进行了一层扩展,可以在Bean的实例化阶段前后执行:
// 继承了BeanPostProcessor,额外提供了两个方法用于在实例化前后的阶段执行
// 因为实例化后紧接着就要进行属性注入,所以这个接口中还提供了一个属性注入的方法
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
 
    // 实例化前执行
 default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
  return null;
 }
 
    // 实例化后置
 default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
  return true;
 }
    
    // 属性注入
    default PropertyValues postProcessPropertyValues(
        PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

        return pvs;
    }
}
  1. Spring内部专用的后置处理器
    可能有的小伙伴认为,第三种后置处理器肯定就是用来在属性注入前后执行了的吧。我只能说,大兄弟,太天真了,看看下面这张图
    这种情况下再为属性注入阶段专门提供两个方法是不是有点多余呢?实际上第三种后置处理器是Spring为了自己使用而专门设计的:
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
 
    // 推测bean的类型,例如在属性注入阶段我们就需要知道符合依赖类型的Bean有哪些
    @Nullable
    default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }
 
    // 推断出所有符合要求的构造函数,在实例化对象的时候我们就需要明确到底使用哪个构造函数
    @Nullable
    default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
        throws BeansException {

        return null;
    }
 
    // 获取一个提前暴露的对象,用于解决循环依赖
    default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
        return bean;
    }

}
总结:
  • Bean 容器找到配置文件中 Spring Bean 的定义。
  • Bean 容器利用 Java Reflection API 创建一个Bean的实例。
  • 如果涉及到一些属性值 利用 set()方法设置一些属性值。
  • 如果 Bean 实现了 BeanNameAware 接口,调用 setBeanName()方法,传入Bean的名字。
  • 如果 Bean 实现了 BeanClassLoaderAware 接口,调用 setBeanClassLoader()方法,传入 ClassLoader对象的实例。
  • 如果Bean实现了 BeanFactoryAware 接口,调用 setBeanClassLoader()方法,传入 ClassLoader对象的实例。
  • 与上面的类似,如果实现了其他 *.Aware接口,就调用相应的方法。
  • 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessBeforeInitialization() 方法
  • 如果Bean实现了InitializingBean接口,执行afterPropertiesSet()方法。
  • 如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。
  • 如果有和加载这个 Bean的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessAfterInitialization() 方法
  • 当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接口,执行 destroy() 方法。
  • 当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。
    在这里插入图片描述
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RachelHwang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值