Spring的两个启动过程具体实现
一、 IOC容器的初始化过程
从图中也可以看出,启动主要包括 BeanDefinition 的 Resource定位、载入和注册三个基本过程:
1. BeanDefinition
的Resource
定位
Resource
接口是所有资源的抽象和访问接口,主要有这样几种:ResourceLoader
接口是资源查找定位策略的统一抽象,具体的资源查找由具体的资源查找实现类给出:
DefaultResourceLoader
: ResourceLoader 下的默认实现类FileSystemResourceLoader
:从文件查找资源2.
BeanDefinition
的载入这个过程就是把用户定义好的Bean表示成IOC容器内部的数据结构—BeanDefinition,方便容器对Bean进行管理。具体是通过
BeanDefinitionReader
来完成BeanDefinition
在IOC容器中的载入。我们会看到在BeanDefinitionReader
接口中有各种loadBeanDefinitions( )
方法:public interface BeanDefinitionReader { /**获取BeanDefinition注册表*/ BeanDefinitionRegistry getRegistry(); ResourceLoader getResourceLoader(); void loadBeanDefinitions(Resource resource) throws BeansException; void loadBeanDefinitions(Resource... resources) throws BeansException; void loadBeanDefinitions(String location) throws BeansException; void loadBeanDefinitions(String... locations) throws BeansException; }
而一般是用XML文件来对
BeanDefinition
进行定义,因此使用XmlBeanDefinitionReader
来完成载入BeanDefinition
到IOC容器的过程。3. BeanDefinition的注册
这一步是将上一步已经载入IOC容器的
BeanDefinition
在IOC容器中进行注册。具体注册是在DefaultListableBeanFactory
的beanDefinitionMap
中,而其中的注册操作方法,则是由BeanDefinitionRegistry
接口来进行操作定义:/** * @description: BeanDefinition注册表,操作BeanDefinition的几种方法 * @author: wjw * @date: 2022/6/17 */ public interface BeanDefinitionRegistry { /** * 向注册表中注册 BeanDefinition * @param beanName * @param beanDefinition */ void registerBeanDefinition(String beanName, BeanDefinition beanDefinition); /** * 利用BeanName查询BeanDefinition * @param beanName * @return * @throws BeansException */ BeanDefinition getBeanDefinition(String beanName) throws BeansException; /** * 判断是否包含指定名称的BeanDefinition * @param beanName * @return */ boolean containsBeanDefinition(String beanName); /** * 返回注册表中所有的BeanName * @return */ String[] getBeanDefinitionNames(); }
完成这些步骤后,
BeanDefinition
就可以被IOC容器所使用了。4.
BeanDefinition
的修改此外,IOC容器也提供了一个
BeanFactoryProcessor
的容器扩展机制,可以在容器实例化对象之前,对注册到容器的BeanDefinition
的相应属性进行修改二、BeanFactoy容器的实例化过程(依赖注入)
这个过程实际上是用户第一次调用
getBean()
来触发的,但是也可以通过在BeanDefinition
中控制lazy-init
属性来完成对Bean
的预实例化。
事实上,对于Spring中的两种容器,BeanFactory是通过getBean()
来触发,而ApplicationContext
则是在容器启动后就完成了对所有BeanDefintion
的实例化
我们先来看看在BeanFactory
中Bean
的生命周期:
主要的步骤有:1.
InstantiationAwareBeanPostProcessor
的postProcessBeforeInstantiation()
方法在实例化
Bean
前执行该方法。2. 实例化
Bean
2.1
getBean()
依赖注入的起点通过调用
getBean()
方法,来执行实例化流程。具体代码在AbstractBeanFactory
中的doGetBean()
:protected <T> T doGetBean(final String name, final Object[] args) { Object sharedInstance = getSingleton(name); if (sharedInstance != null) { // 如果是 FactoryBean,则需要调用 FactoryBean#getObject return (T) getObjectForBeanInstance(sharedInstance, name); } BeanDefinition beanDefinition = getBeanDefinition(name); //生成所需要的Bean,并对Bean初始化进行处理,具体处理在AbstractAutowireCapableBeanFactory中 Object bean = createBean(name, beanDefinition, args); return (T) getObjectForBeanInstance(bean, name); } private Object getObjectForBeanInstance(Object beanInstance, String beanName) { if (!(beanInstance instanceof FactoryBean)) { return beanInstance; } Object object = getCachedObjectForFactoryBean(beanName); if (object == null) { FactoryBean<?> factoryBean = (FactoryBean<?>) beanInstance; object = getObjectFromFactoryBean(factoryBean, beanName); } return object; } protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException; protected abstract Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException;
我们看到,首先会调用
getSingleton()
方法,从缓存中获取Bean,处理那些已经被创建过的单例 Bean。防止被重复创建:
- 如果从缓存中获取了Bean,那么就通过获取的Bean,调用
getObjectForBeanInstance()
方法,来取得FactoryBean
如果无法从缓存中获取单例Bean,那么调用
getBeanDefinition( )
和createBean()
方法,创造对应所需的BeanDefinition 和 Bean。然后利用创建的 Bean来调用getObjectForBeanInstance()
方法来获取FactoryBean
2.2
createBean()
生成所需的Bean
实际上核心部分在
AbstractAutowireCapableBeanFactory
类中,createBean()
不但生成了所需的Bean
,而且还对Bean
初始化进行相应的处理,具体代码如下:protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException { Object bean = null; try { // 判断是否返回代理 Bean 对象 bean = resolveBeforeInstantiation(beanName, beanDefinition); if (null != bean) { return bean; } // 实例化 Bean bean = createBeanInstance(beanDefinition, beanName, args); // 给 Bean 填充属性 applyPropertyValues(beanName, bean, beanDefinition); // 执行 Bean 的初始化方法和 BeanPostProcessor 的前置和后置处理方法 bean = initializeBean(beanName, bean, beanDefinition); } catch (Exception e) { throw new BeansException("Instantiation of bean failed", e); } // 注册实现了 DisposableBean 接口的 Bean 对象 registerDisposableBeanIfNecessary(beanName, bean, beanDefinition); // 判断 SCOPE_SINGLETON、SCOPE_PROTOTYPE if (beanDefinition.isSingleton()) { registerSingleton(beanName, bean); } return bean; }
2.2.1
resovleBeforeInstantiation()
一步一步来看,首先会调用
resolveBeforeInstantiation()
方法(在源码中,会先判断创建的Bean是否可以实例化,类是否可以通过类装载器载入),如果Bean 配置了PostProcessor,这里返回的会是一个 proxy 代理。
而且在该方法调用中,如果容器注册实现了InstantiationAwareBeanPostProcessor
接口,则在实例化Bean前,将调用这个接口的的postProcessBeforeInstantiation()
方法:protected Object resolveBeforeInstantiation(String beanName, BeanDefinition beanDefinition) { Object bean = applyBeanPostProcessorsBeforeInstantiation(beanDefinition.getBeanClass(), beanName); if (null != bean) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } return bean; } protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) { for (BeanPostProcessor beanPostProcessor : getBeanPostProcessors()) { if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) { Object result = ((InstantiationAwareBeanPostProcessor) beanPostProcessor).postProcessBeforeInstantiation(beanClass, beanName); if (null != result) return result; } } return null; }
2.2.2
createBeanInstance( )
其次来到核心的
createBeanInstance()
方法,用于实例化 Bean(在源码中,会先调用doCreateBean( )
来处理一些BeanWrapper、单例Bean等等逻辑后再调用createBeanInstance()
),这里通过调用实例化策略来实例化 Bean:protected Object createBeanInstance(BeanDefinition beanDefinition, String beanName, Object[] args) { Constructor constructorToUse = null; Class<?> beanClass = beanDefinition.getBeanClass(); Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors(); for (Constructor ctor : declaredConstructors) { if (null != args && ctor.getParameterTypes().length == args.length) { constructorToUse = ctor; break; } } return getInstantiationStrategy().instantiate(beanDefinition, beanName, constructorToUse, args); }
2.2.3
applyPropertyValues()
填充属性值接下来是给 Bean 填充属性值:
protected void applyPropertyValues(String beanName, Object bean, BeanDefinition beanDefinition) { try { PropertyValues propertyValues = beanDefinition.getPropertyValues(); for (PropertyValue propertyValue : propertyValues.getPropertyValues()) { String name = propertyValue.getName(); Object value = propertyValue.getValue(); if (value instanceof BeanReference) { // A 依赖 B,获取 B 的实例化 BeanReference beanReference = (BeanReference) value; value = getBean(beanReference.getBeanName()); } // 属性填充 BeanUtil.setFieldValue(bean, name, value); } } catch (Exception e) { throw new BeansException("Error setting property values:" + beanName); } }
2.2.4 执行Bean的初始化
initializeBean()
private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) { // invokeAwareMethods if (bean instanceof Aware) { if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(this); } if (bean instanceof BeanClassLoaderAware) { ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader()); } if (bean instanceof BeanNameAware) { ((BeanNameAware) bean).setBeanName(beanName); } } // 1. 执行 BeanPostProcessor Before 处理 Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName); // 执行 Bean 对象的初始化方法 try { invokeInitMethods(beanName, wrappedBean, beanDefinition); } catch (Exception e) { throw new BeansException("Invocation of init method of bean[" + beanName + "] failed", e); } // 2. 执行 BeanPostProcessor After 处理 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); return wrappedBean; }
在初始化前,会设置相关的Aware接口,比如
BeanFactoryAware
、BeanClassLoaderAware
和BeanNameAware
接着调用applyBeanPostProcessorsBeforeInitialization()
,执行BeanPostProcessor
的postProcessBeforeInitialization()
方法public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { Object current = processor.postProcessBeforeInitialization(result, beanName); if (null == current) return result; result = current; } return result; }
然后才来到执行Bean对象的初始化方法:
invokeInitMethods()
:private void invokeInitMethods(String beanName, Object bean, BeanDefinition beanDefinition) throws Exception { // 1. 实现接口 InitializingBean if (bean instanceof InitializingBean) { ((InitializingBean) bean).afterPropertiesSet(); } // 2. 注解配置 init-method {判断是为了避免二次执行销毁} String initMethodName = beanDefinition.getInitMethodName(); if (StrUtil.isNotEmpty(initMethodName)) { Method initMethod = beanDefinition.getBeanClass().getMethod(initMethodName); if (null == initMethod) { throw new BeansException("Could not find an init method named '" + initMethodName + "' on bean with name '" + beanName + "'"); } initMethod.invoke(bean); } }
首先调用
InitializingBean
的afterPropertiesSet()
方法。接着通过init-method
属性配置初始化方法。最后再回到initializeBean()
方法中,再调用BeanPostProcessor
的postProcessAfterInitialization()
方法。
接下来回到最初的createBean()
方法里,注册实现DisposableBean
接口的 Bean 对象,通过该方法registerDisposableBeanIfNecessary()
来实现:protected void registerDisposableBeanIfNecessary(String beanName, Object bean, BeanDefinition beanDefinition) { // 非 Singleton 类型的 Bean 不执行销毁方法 if (!beanDefinition.isSingleton()) return; if (bean instanceof DisposableBean || StrUtil.isNotEmpty(beanDefinition.getDestroyMethodName())) { registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, beanDefinition)); } }
- 如果遇到多例,则将准备就绪的
Bean
传给调用者 如果遇到单例对象,执行销毁方法,这里是将
Bean
注册进disposableBeans
的Map中去,也就是这一段:registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, beanDefinition));
利用适配器模式将该
Bean
注册进存放disposableBeans
中去。接下来则是调用DisposableBean
的destroy()
方法:主要是通过在DisposableBeanAdapter
类里面:public class DisposableBeanAdapter implements DisposableBean { private final Object bean; private final String beanName; private String destroyMethodName; public DisposableBeanAdapter(Object bean, String beanName, BeanDefinition beanDefinition) { this.bean = bean; this.beanName = beanName; this.destroyMethodName = beanDefinition.getDestroyMethodName(); } @Override public void destroy() throws Exception { /**实现 DisposableBean 接口*/ if (bean instanceof DisposableBean) { ((DisposableBean) bean).destroy(); } /**注解配置 destroy-method 的销毁方法*/ if (StrUtil.isNotEmpty(destroyMethodName) && (bean instanceof DisposableBean && "destroy".equals(this.destroyMethodName))) { Method destroyMethod = bean.getClass().getMethod(destroyMethodName); if (destroyMethod == null) { throw new BeansException("Couldn't find a destroy method named '" + destroyMethodName + "' on bean with name '" + beanName + "'"); } destroyMethod.invoke(bean); } } }
主要有两个步骤,首先调用
DisposableBean
的destory()
方法,然后再通过destory-method
配置属性的销毁方法。到此,完成Bean的生命周期Bean 生命周期接口相关的配置
- 可以通过 <Bean> 的
init-method
和destroy-method
属性的配置方式为Bean
指定初始化和销毁方法,这种方式对Bean
生命周期的控制效果相当于实现InitializingBean
和DisposableBean
接口的效果 BeanFactoryAware
接口让Bean感知容器,BeanNameAware
接口让Bean获得配置文件中对应的配置名称。Spring两个启动过程的大体步骤
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。