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方法如何完成初始化 还有循环依赖的问题 。