Spring框架最主要的东西就是IOC注入,那么它是如何将java类变成 bean 然后注入容器 又是如何将bean实例化的呢
首先我们需要了解什么是BeanFactory ,BeanFactory 是一个接口 他有很多子接口, 简单的理解就是一个容器,用来管理bean.整一个流程
其中ApplicationContext我们都很熟悉,就是BeanFactory的一个子接口.
在启动阶段 系统通过扫描注解 读取XML等方式获取bean的属性信息,然后转化成BeanDefinition ,BeanDefinition可以理解为一个模板类 存放bean的方法字段等一系列信息
然后通过BeanFactory 的实现类会把这些BeanDefinition 注册到容器中 本质就是放到一个ConcurrentHashMap中,在
需要实例化的时候拿出来。
下面这个方法registerBeanDefinition就是注册BeanDefinition到容器
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "Bean definition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition)beanDefinition).validate();
} catch (BeanDefinitionValidationException var4) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var4);
}
}
Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!this.allowBeanDefinitionOverriding) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': there's already [" + oldBeanDefinition + "] bound");
}
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName + "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
} else {
this.beanDefinitionNames.add(beanName);
}
this.beanDefinitionMap.put(beanName, beanDefinition);
this.removeSingleton(beanName);
}
此时Bean的定义其实已经存储在bean工厂里了 那么如何去实例化呢 .beanFactroy有个getBean方法 就是实例化的入口
我们拿其中一个beanFactroy的实现类举例
我们进入AbstractBeanFactory 看到
public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException { return this.doGetBean(name, requiredType, (Object[])null, false); }
一直贴代码肯定看的头晕眼花 我这里就简单写了
AbstractBeanFactory 中我们发现一个getBean方法 这就是beanshih实例化的路口方法
------方法中又调用了doGetBean方法:
doGetBean方法中先会根据beanname判断缓存中有没有 因为bean创建后默认是单例的 会先放到缓存中 下次如果要用就可以免去重复创建了,这里会根据beandefintion中的信息判断是单例还是多例,单例会加入缓存 方便下次使用。
---doGetBean方法中又调用了createBean方法:
进入方法观察 ,createBean中通过resolveBeanClass解析bean的类型等操作 。
---createBean方法中调用了doCreateBean:
这里贴上一代码 解释一下:
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
//该BeanWrapper持有将要实例化的bean对象 BeanWrapper instanceWrapper = null; //如果是单例模式,则清除同名的bean对象 if (mbd.isSingleton()) { instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName); } //实例化bean if (instanceWrapper == null) { instanceWrapper = this.createBeanInstance(beanName, mbd, args); } Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } Object var7 = mbd.postProcessingLock; synchronized(mbd.postProcessingLock) { if (!mbd.postProcessed) { try { //MergedBeanDefinitionPostProcessor后处理器修改已合并的bean定义 this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable var17) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17); } mbd.postProcessed = true; } } boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName); if (earlySingletonExposure) { if (this.logger.isDebugEnabled()) { this.logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } this.addSingletonFactory(beanName, () -> { return this.getEarlyBeanReference(beanName, mbd, bean); }); } Object exposedObject = bean; try { //此时已完成bean的实例化 这里是给bean的属性赋值 this.populateBean(beanName, mbd, instanceWrapper); //bean的初始化 exposedObject = this.initializeBean(beanName, exposedObject, mbd); } catch (Throwable var18) { if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) { throw (BeanCreationException)var18; } throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18); } //依赖检查 if (earlySingletonExposure) { Object earlySingletonReference = this.getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) { String[] dependentBeans = this.getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length); String[] var12 = dependentBeans; int var13 = dependentBeans.length; for(int var14 = 0; var14 < var13; ++var14) { String dependentBean = var12[var14]; if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); } } } } try { //将bean注册一个DisposableBean 用于容器销毁是销毁该bean this.registerDisposableBeanIfNecessary(beanName, bean, mbd); //返回bean的实例 return exposedObject; } catch (BeanDefinitionValidationException var16) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16); } }
至此spring成功完成了bean的创建和实例化,当然我这只是粗劣地讲解,其中的许多细节我们没有细究 ,比如initializeBean方法如何完成初始化 还有循环依赖的问题 。