SpringIoC依赖注入的过程(一)
SpringIoC依赖注入的过程(一) 对spring稍有些了解的人都知道,依赖注入的发生是在第一次向容器索要bean时触发的。BeanFanctory为我们提供了一系列的getBean接口,它的实现大部分都在AbstractBeanFactory中,最终都会调用到doGetBean(final String name, final Class requiredType, final
·
SpringIoC依赖注入的过程(一)
对spring稍有些了解的人都知道,依赖注入的发生是在第一次向容器索要bean时触发的。BeanFanctory为我们提供了一系列的getBean接口,它的实现大部分都在AbstractBeanFactory中,最终都会调用到doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)这个方法。不管各种getBean方法需要什么样的参数,都得必须组合成上面的四个参数提供给doGetBean,并且bean的名字是必须的。虽然BeanFactory中有直接根据类型获取的方法getBean(Class<T> requiredType),但是AbstractBeanFactory并没有实现。
doGetBean的第一步先检查是否有已经缓存好的单例bean,如果有则取出这个bean对象。没有取到缓存的单例,第二步尝试到双亲BeanFactory中去寻找,若找到则直接返回。接下来会取出当前bean的所有依赖bean,并且递归的调用getBean以先创建当前bean依赖的bean(这里说的依赖bean不包括声明的Autowire域,也不包括xml配置文件中通过ref引用的bean)。下面是doGetBean的这部分代码:
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);
}
}
处理完上面所说的依赖bean,下面会判断bean的scope是什么,然后根据不同的scope采用不同的方法来获取bean。不管怎样,如果bean还没有创建的话,它们都会通过createBean方法来创建一个全新的bean。在spring的应用中,大部分的bean都是单例的,所以以单例bean为例子,看看怎么来获取想要的bean。
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
上面的getSingleton方法定义在DefaultSingletonBeanRegistry中,它是
AbstractBeanFactory的父类,它会返回一个创建好的bean,代码如下:
public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
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<Exception>();
}
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);
}
addSingleton(beanName, singletonObject);
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>();
getSingleton方法首先锁住了singletonObjects对象,这个
singletonObjects是DefaultSingletonBeanRegistry中注册的所有单例bean。然后再次判断是否已经有创建好的单例bean,这样做的目的是为了在高并发的情况下产生创建多个bean实例的情况。类似于经典的双重检查的单例模式,但是是线程安全的,因为singletonObjects是一个线程安全的ConcurrentHashMap,当程序进入同步块从singletonObjects获取缓存的单例的时候,要么获取不到,要么获取到创建好的单例,绝对不会得到未创建好的中间状态的单例实例。略过线程安全的问题,进入到同步块内仍然取不到缓存好的单例怎么办呢?通过singletonFactory.getObject()创建一个,这个singletonFactory就是刚刚调用getSingleton方法传入的ObjectFactory类型的匿名类,通过他回调了AbstractAutowireCapableBeanFactory中的createBean方法。createBean最主要的工作就是调用doCreateBean方法来创建一个全新的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);
}
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);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!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.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
上面就是doCreateBean得全部代码。它的首先第一步通过createBeanInstance创建bean实例,并且放到BeanWrapper中返回。可以看到这个方法返回的
BeanWrapper赋值到了instanceWrapper中,然后用它的getWrappedInstance()取出了创建出来的bean。注意,这时候的bean相当于刚刚执行完构造方法的Java对象,关于这个bean的依赖关系以及其他的一些初始化操作都还没有执行。
创建好bean实例之后,接下来就是通过一系列的后置处理器来注入当前bean依赖的其他bean,并且进行相应的初始化操作。依赖的bean是怎样注入进来的,bean的PostConstructor、afterPropertiesSet以及各种*aware接口的回调是怎么被调用的?。下一篇文章详细整理。
更多推荐
已为社区贡献3条内容
所有评论(0)