Spring IOC源码-bean加载 博客分类: spring springiocbean加载
程序员文章站
2024-02-06 20:21:16
...
1、装载bean的第一步,调用doGetBean(name,...)方法
(1)转换对应的beanName,参数里面的name未必是beanName,可能是别名或者factoryBean
(2)首先尝试从缓存中加载单例
(3)如果从缓存中拿到了bean,调用getObjectForBeanInstance 将bean实例化
(4)原型模式依赖检查
(5)通过getParentBeanFactory获取parentBeanFactory
(6)获取RootBeanDefinition
(7)针对不同的scope进行bean的创建
(8)类型转换
2、从缓存中获取单例对象,其中,
singletonObjects是一个map,存储实例化后的对象
earlySingletonObjects也是一个map,存储实例化后的对象,与singletonObjects的区别是,当一个单例的bean被放到这个map中以后,当bean还在创建中的时候就可以通过getbean获取到了,用来检测循环引用
singletonFactories:保存beanName和创建bean的工厂之间的映射关系
registeredSingletons:保存当前所有已经注册的bean
3、根据不同的scope创建bean, 以单例为例:getSingleton()方法的第一个参数是beanName, 第二个参数是一个接口:ObjectFactory,这个接口提供一个getObject方法在getSingleton中的singletonObject = singletonFactory.getObject();时候使用。
下面看getObject的时候都做了什么
getObject会使用AbstractBeanFactory类的抽象方法:
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException;
他的实现写在AbstractAutowireCapableBeanFactory里面,继承结构图如下:
4、createBean进去以后首先找到BeanDefinition,然后调用doCreateBean()创建真正的bean,doCreateBean中完成了以下几件事:
(1)如果需要创建的bean是单例,需要首先清除缓存
(2)实例化bean,调用createBeanInstance()方法,将beanDefinition转化为BeanWrapper
这个过程包含以下几个步骤
- 如果存在工厂方法,则使用工厂方法进行初始化
- 当一个类有多个构造函数的时候,每个构造函数都有不同的参数,需要根据参数锁定构造函数并进行初始化
- 如果即不存在工厂方法,也不存在带有参数的构造方法,使用默认构造方法进行bean的实例、
(3)调用populateBean进行属性的填充
(4)调用registerDisposableBeanIfNecessary进行bean的注册
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args); //创建beanWrapper
}
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<Object>() {
@Override
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);
}
}
......
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd); //注册bean
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
5、使用createBeanInstance创建bean实例
获取beanName对应的class
- 如果存在工厂方法,使用工厂方法执行bean的初始化策略
- 解析构造函数并进行构造函数的实例化
里面比较重要的方法是
autowireConstructor(beanName, mbd, null, null);(调用带有参数的构造方法)和instantiateBean(beanName, mbd);(调用无参构造方法)
6、使用populateBean进行属性注入
该方法中最重要的是对autowireByName(beanName, mbd, bw, newPvs);和对autowireByType(beanName, mbd, bw, newPvs);方法的调用,
最后再使用applyPropertyValues(beanName, mbd, bw, pvs); 将所有的属性填充到BeanWrapper中
(4)getBean方法中无论是要创建那种类型的bean最终都是通过getObjectForBeanInstance(...)方法生成,该方法是beanFactory与factoryBean的桥梁,在这个方法中调用BeanFactory通过factoryBean去创建bean
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
//如果bean不是一个FactoryBean则不做任何处理
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
(3)getObjectFromFactoryBean
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
}
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
}
}
return (object != NULL_OBJECT ? object : null);
}
}
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
(4)doGetObjectFromFactoryBean
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
return factory.getObject();
}
}, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
object = factory.getObject();
}
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
// Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
if (object == null && isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
return object;
}
上一篇: Spring架构揭秘-IOC容器 博客分类: Spring springiocwebjava架构
下一篇: 03-Spring3 依赖注入(DI)A_配置使用【转】 博客分类: Spring JavaSpringBeanDI依赖注入
推荐阅读
-
Spring IOC源码-bean加载 博客分类: spring springiocbean加载
-
Spring IOC 源码-bean解析 博客分类: spring springioc源码
-
Spring学习(二)---在IoC容器中装配Bean 博客分类: Spring 3.x 企业应用开发笔记 springbeanioc框架
-
Spring IoC浅析 博客分类: Spring Spring容器IoCAOP源码
-
Spring的IOC源码解读&UML 博客分类: javaspringiocbean javaspringiocbean
-
Spring源码剖析2:Spring IOC容器的加载过程
-
spring源码深度解析— IOC 之 开启 bean 的加载
-
Spring源码剖析2:Spring IOC容器的加载过程
-
深入了解Spring源码4:懒加载的单例Bean获取过程分析
-
# Spring IOC容器:BeanFactory、ApplicationContext和Bean的加载