摘要:这篇文章是我学习分析其源码时总结的,其目的并非是完全理解源码信息,但是根据容器如何从文件到的实例初始化进行了一个流程的梳理,希望可以对大家理解源码有一定的帮助。
这篇文章是我学习spring IoC 分析其源码时总结的,其目的并非是完全理解源码信息,但是根据spring IoC 容器如何从xml文件到bean的实例初始化进行了一个流程的梳理,希望可以对大家理解源码有一定的帮助。话不多少,我们直接来看。
这里,我是用ApplicationContext来进行介绍,毕竟项目中大部分还是使用的这个容器。容器启动的入口我们可以从AbstractApplicationContext类的refresh方法看起。
Spring IoC容器对Bean定义资源的载入是从refresh()函数开始的,refresh()是一个模板方法,refresh()方法的作用是:在创建IoC容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在refresh之后使用的是新建立起来的IoC容器。refresh的作用类似于对IoC容器的重启,在新建立好的容器中对容器进行初始化,对Bean定义资源进行载入。
refresh
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset "active" flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } } }
上边有两个很重要的方法:
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
这个方法就是根据Xml配置文件解析Bean的信息生成BeanDifinition,然后注册到BeanDefinitionRegistry中,即bean信息的装载注册阶段
beanFactory.preInstantiateSingletons();
这个方法看其注释我们就可以理解,它是实例化所有非懒加载的单例bean。
AbstractApplicationContext的obtainFreshBeanFactory()方法调用子类容器的refreshBeanFactory()方法,启动容器载入Bean定义资源文件的过程,代码如下:
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { //这里使用了委派设计模式,父类定义了抽象的refreshBeanFactory()方法,具体实现调用子类容器的refreshBeanFactory()方法 refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }
AbstractApplicationContext类中只抽象定义了refreshBeanFactory()方法,容器真正调用的是其子类AbstractRefreshableApplicationContext实现的 refreshBeanFactory()方法。代码如下:
protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
在这个方法中,先判断BeanFactory是否存在,如果存在则先销毁beans并关闭beanFactory,接着创建DefaultListableBeanFactory,并调用loadBeanDefinitions(beanFactory)装载bean定义。
我们在其子类AbstractXmlApplicationContext最终可以看到下面这个方法,此方法就是真正从XML文件中读取并解析Bean的信息,放在对应的BeanDefinition中
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // Create a new XmlBeanDefinitionReader for the given BeanFactory. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // Configure the bean definition reader with this context"s // resource loading environment. beanDefinitionReader.setEnvironment(this.getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // Allow a subclass to provide custom initialization of the reader, // then proceed with actually loading the bean definitions. initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); }
再看preInstantiateSingletons()
public void preInstantiateSingletons() throws BeansException { if (this.logger.isInfoEnabled()) { this.logger.info("Pre-instantiating singletons in " + this); } ListbeanNames; synchronized (this.beanDefinitionMap) { // Iterate over a copy to allow for init methods which in turn register new bean definitions. // While this may not be part of the regular factory bootstrap, it does otherwise work fine. beanNames = new ArrayList (this.beanDefinitionNames); } for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { final FactoryBean> factory = (FactoryBean>) getBean(FACTORY_BEAN_PREFIX + beanName); boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged(new PrivilegedAction () { public Boolean run() { return ((SmartFactoryBean>) factory).isEagerInit(); } }, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } else { getBean(beanName); } } } }
其中我们需要关注getBean(beanName)这个方法,此方法中进行了bean的实例化和初始化;我们可以进入这个方法中,看到doGetBean() 这个方法
protectedT doGetBean( final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { ... ... //这一部分是先从缓存中获取对应的bean;如果有的话,返回缓存中的单例bean; Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isDebugEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("Returning eagerly cached instance of singleton bean "" + beanName + "" that is not fully initialized yet - a consequence of a circular reference"); } else { logger.debug("Returning cached instance of singleton bean "" + beanName + """); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { ... ... /** * Return a merged RootBeanDefinition, traversing the parent bean definition * if the specified bean corresponds to a child bean definition. */ final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dependsOnBean : dependsOn) { getBean(dependsOnBean); registerDependentBean(dependsOnBean, beanName); } } // Create bean instance. if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory
上边的代码中,我们需要关心的是
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
获取到对应beanName的BeanDefinition,这里显然是做了些包装(RootBeanDefinition);
由于在项目中,绝大部分bean都是单例的,所以我们只关心单例类型的bean的创建
if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory
注意,这里重新 实现了ObjectFactory中的getObject()方法,这个对下面的理解有很大帮助。我们先进入getSingleton()方法中
public Object getSingleton(String beanName, ObjectFactory singletonFactory) { Assert.notNull(beanName, ""beanName" must not be null"); synchronized (this.singletonObjects) { //从缓存中获取对应的bean Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while the singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); } if (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean "" + beanName + """); } beforeSingletonCreation(beanName); boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet(); } try { singletonObject = singletonFactory.getObject(); } catch (BeanCreationException ex) { if (recordSuppressedExceptions) { for (Exception suppressedException : this.suppressedExceptions) { ex.addRelatedCause(suppressedException); } } throw ex; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } afterSingletonCreation(beanName); } //在这里将实例化的bean放入容器中; addSingleton(beanName, singletonObject); } return (singletonObject != NULL_OBJECT ? singletonObject : null); } }
这里边我们需要关注的有
beforeSingletonCreation(beanName);
从名称我们大概可以猜出来这个方法的一些作用:在单例bean创建之前所要做的事;
singletonObject = singletonFactory.getObject();
看到这里,你会想到什么?前面所说的在上一层重新实现了次方法,所以这一块得注意,它执行的是重新实现后的方法,等下具体分析。
afterSingletonCreation(beanName);
对应beforeSingletonCreation,这个就是在单例bean创建之后所要做的事;
接下来,我们回头看一下重新实现的singletonFactory.getObject()里调用了createBean(beanName, mbd, args);
我们进入createBean(beanName, mbd, args)
protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException { if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean "" + beanName + """); } // Make sure bean class is actually resolved at this point. resolveBeanClass(mbd, beanName); // Prepare method overrides. try { mbd.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. Object bean = resolveBeforeInstantiation(beanName, mbd); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } Object beanInstance = doCreateBean(beanName, mbd, args); if (logger.isDebugEnabled()) { logger.debug("Finished creating instance of bean "" + beanName + """); } return beanInstance; }
在这里,我们可以看到
Object beanInstance = doCreateBean(beanName, mbd, args);
在这个方法中进行备案的实例化(有人这时候会说,怎么这么就还没有看到真正的bean实例化,没办法,spring自己还要实现自己的一些东西,这些我们不关注,但是不代表没有必要,所以耐心看下去吧)
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) { // Instantiate the bean. //这个类将作为最终的bean单例放入容器中 BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null); Class> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null); // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); mbd.postProcessed = true; } } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. //处理循环依赖的问题 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean "" + beanName + "" to allow for resolving potential circular references"); } addSingletonFactory(beanName, new ObjectFactory() { public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } }); } // Initialize the bean instance. Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null) { exposedObject = initializeBean(beanName, exposedObject, mbd); } } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } ... ... }
此方法较长,我们只需要关心我们需要关心的。
BeanWrapper instanceWrapper = null;
此类将作为最终的单例bean放入容器中,这个类将会是对应bean的一个封装;
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
允许其他修改beanDefinition,这主要是允许其他组件提供xml不能提供的信息。如使用Annotation增强Bean定义等。这通过类ergedBeanDefinitionPostProcessor来完成,如果容器中提供了此类实现,则会调用进行bean增强。
populateBean(beanName, mbd, instanceWrapper);
此方法里是利用InstantiationAwareBeanPostProcessor将bean进行填充,以及autowire标签的处理
exposedObject = initializeBean(beanName, exposedObject, mbd);
重头戏来了,这个才是我们最要关心的,在里边会进行bean的实例化和初始化
进入initializeBean
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction
这里边有三个重要的方法
invokeAwareMethods(beanName, bean);
查看该bean是否实现了相关的Aware接口,如果有,将其进行装配;
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
invokeInitMethods(beanName, wrappedBean, mbd);
这里利用Java反射机制将bean对应的beanDefinition信息进行设置;
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
spring提供了一个接口类-BeanPostProcessor,我们叫他:bean的加工器,应该是在bean的实例化过程中对bean做一些包装处理,里边提供两个方法applyBeanPostProcessorsBeforeInitialization和applyBeanPostProcessorsAfterInitialization。
根据以上代码,我们得知,在invokeInitMethods的执行前后,spring会分别调用所有的BeanPostProcessor,执行其中的方法,那么invokeInitMethods的具体内容我们仍需要看下,发现此方法主要作用有两个:
判断bean是否继承了InitializingBean,如果继承接口,执行afterPropertiesSet()方法
获得是否设置了init-method属性,如果设置了,就执行设置的方法
这里几个典型的应用场景如:
解析bean的注解,将注解中的字段转化为属性
统一将属性在执行前,注入bean中,如数据库访问的sqlMap,如严重服务,这样不需要每个bean都配置属性
打印日志,记录时间等。
详细了解BeanPostProcessor的使用可以参考这里BeanPostProcessor的使用
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable { boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isDebugEnabled()) { logger.debug("Invoking afterPropertiesSet() on bean with name "" + beanName + """); } if (System.getSecurityManager() != null) { try { AccessController.doPrivileged(new PrivilegedExceptionAction
到了这里,spring才真正地实例化并初始化bean。 所以在进入initializeBean方法里,我们大概可以总结出bean的初始化顺序:
XXAware接口的实现->postProcessBeforeInitialization->InitializingBean的afterPropertiesSet -> custom Init方法->postProcessAfterInitialization
如有错误,欢迎指正。如果对你有帮助的话,顺便点个赞哈!
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/67555.html
摘要:在上文中,我实现了一个很简单的和容器。比如,我们所熟悉的就是在这里将切面逻辑织入相关中的。初始化的工作算是结束了,此时处于就绪状态,等待外部程序的调用。其中动态代理只能代理实现了接口的对象,而动态代理则无此限制。 1. 背景 本文承接上文,来继续说说 IOC 和 AOP 的仿写。在上文中,我实现了一个很简单的 IOC 和 AOP 容器。上文实现的 IOC 和 AOP 功能很单一,且 I...
摘要:实例化时,发现又依赖于。一些缓存的介绍在进行源码分析前,我们先来看一组缓存的定义。可是看完源码后,我们似乎仍然不知道这些源码是如何解决循环依赖问题的。 1. 简介 本文,我们来看一下 Spring 是如何解决循环依赖问题的。在本篇文章中,我会首先向大家介绍一下什么是循环依赖。然后,进入源码分析阶段。为了更好的说明 Spring 解决循环依赖的办法,我将会从获取 bean 的方法getB...
摘要:源码分析源码一览本节,我们先来看一下填充属性的方法,即。所有的属性值是在方法中统一被注入到对象中的。检测是否存在与相关的或。这样可以在很大程度上降低源码分析的难度。若候选项是非类型,则表明已经完成了实例化,此时直接返回即可。 1. 简介 本篇文章,我们来一起了解一下 Spring 是如何将配置文件中的属性值填充到 bean 对象中的。我在前面几篇文章中介绍过 Spring 创建 bea...
摘要:你也会了解到构造对象的两种策略。构造方法参数数量低于配置的参数数量,则忽略当前构造方法,并重试。通过默认构造方法创建对象看完了上面冗长的逻辑,本节来看点轻松的吧通过默认构造方法创建对象。 1. 简介 本篇文章是上一篇文章(创建单例 bean 的过程)的延续。在上一篇文章中,我们从战略层面上领略了doCreateBean方法的全过程。本篇文章,我们就从战术的层面上,详细分析doCreat...
摘要:关于创建实例的过程,我将会分几篇文章进行分析。源码分析创建实例的入口在正式分析方法前,我们先来看看方法是在哪里被调用的。时,表明方法不存在,此时抛出异常。该变量用于表示是否提前暴露单例,用于解决循环依赖。 1. 简介 在上一篇文章中,我比较详细的分析了获取 bean 的方法,也就是getBean(String)的实现逻辑。对于已实例化好的单例 bean,getBean(String) ...
阅读 1562·2021-11-24 09:39
阅读 2995·2021-11-22 15:24
阅读 3057·2021-10-26 09:51
阅读 3242·2021-10-19 11:46
阅读 2857·2019-08-30 15:44
阅读 2178·2019-08-29 15:30
阅读 2506·2019-08-29 15:05
阅读 739·2019-08-29 10:55