在前两篇博客里,讲了spring对于自定义标签和默认标签的初始化过程。对于bean标签的解析注册,这只是IOC的第一步,而我们知道,我们经常用的bean默认是单例的,而且是spring为我们提供好的。这就涉及到IOC的第二步,为bean生成实例。
如果对spring bean的解析注册不熟悉的,可以参照 spring源码解析之一 和 spring源码解析之二
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();
}
前两篇对于bean标签的解析注册,我们都是从容器初始化的refresh方法中的obtainFreshBeanFactory()进去的
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
这个方法执行完毕后,返回beanFactory,我们可以看一下banFactory中存放的东西。(工程代码是 上节的自定义标签的那个工程)。
如下,在beanFactory中我们可以看到BeanDefinitionMap中,已经存放了beanName和BeanDefinition的对应信息,但是还没有实例化对象出来。
由于我们的配置的bean默认是单例的,而且lazy-init属性没有设置,而这个属性默认为false。非懒加载的单例的bean,进入 最后的 finishBeanFactoryInitialization(beanFactory)进行实例化。
直接进入这个方法,下面的代码是进入后,finishBeanFactoryInitialization的处理流程。getBean(weaverAwareName),用于加载spring bean时,织入第三方模块,如AspectJ。这个在讲AOP的时候,会用到。在现在这个工程下,获取到的weaverAwaeName是null。
我们需要进入最后一个preInstantiateSingletons()方法。从它的注释也能看出,它是加载non-lazy-init的singletons。
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
进入到preInstanttiateSingleton()方法后,会在最后的else里调用getBean(beanName)方法,然后又调用doGetBean()方法。所以我们进入doGetBean()方法。
这个方法里的代码很多,只取了开头的几句代码。
protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = this.transformedBeanName(name);
Object sharedInstance = this.getSingleton(beanName);
Object bean;
if(sharedInstance != null && args == null) {
if(this.logger.isDebugEnabled()) {
if(this.isSingletonCurrentlyInCreation(beanName)) {
this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
} else {
this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} else {
在上面的代码中能看出来,通过getSingleton(beanName)获取单例,这个方法会直接从beanFactory的singlentonObjects获取相应名字的bean。因为这个时候,我们的bean还没实例化,所以这个方法返回一个null。sharedInstance为空后,最后还会进入到重载的getSingleton()方法,如下。
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
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。我们先进入createBean方法。从这个名字,也能看出这是创建bean,然后返回包含这个创建的bean的Factory。 所以我们先去看看怎么创建bean,然后再跟着代码返回来。进入createBean后,代码如下:
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.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, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
Object beanInstance = doCreateBean(beanName, mbdToUse, args);//进入
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
从上面可以看出,真正的方法在doCreateBean里面,进去之后。在初始化bean的实例前,需要看他是否是单例,并移除之前创建的。由于doCreateBean这个方法里面的内容很多,所以将这个方法里的内容按照先后顺序,一部分一部分分析。
doCreate第一部分:Instantiate the bean将bean初始化。
先判断mbd是否是单例的bean,如果是那就从bean实例的缓存里,移除相同名字的bean。然后通过调用createBeanInstance()创建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;
}
}
那么进入创建bean实例的方法:
instanceWrapper = createBeanInstance(beanName, mbd, args);
进入后,在由于我们定义的bean非常简单,没有注入属性,所以一直在最后调用了简单的instantiateBean()方法。
instantiateBean(beanName, mbd);
进入之后然后调用如下的方法:
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
进入之后,先获取bean的class,然后通过class获取构造方法,然后调用工具类BeanUtils进行初始化。进入这个方法。
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
if (bd.getMethodOverrides().isEmpty()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
@Override
public Constructor<?> run() throws Exception {
return clazz.getDeclaredConstructor((Class[]) null);
}
});
}
else {
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Exception ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
进入BeanUtils.instantiate()之后,就是最终获取实例的方法了。下面就是这个获取实例的全部代码,可以看到它是通过构造方法的newInstance()进行实例化。
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null");
try {
ReflectionUtils.makeAccessible(ctor);
return ctor.newInstance(args);
}
catch (InstantiationException ex) {
throw new BeanInstantiationException(ctor.getDeclaringClass(),
"Is it an abstract class?", ex);
}
catch (IllegalAccessException ex) {
throw new BeanInstantiationException(ctor.getDeclaringClass(),
"Is the constructor accessible?", ex);
}
catch (IllegalArgumentException ex) {
throw new BeanInstantiationException(ctor.getDeclaringClass(),
"Illegal arguments for constructor", ex);
}
catch (InvocationTargetException ex) {
throw new BeanInstantiationException(ctor.getDeclaringClass(),
"Constructor threw exception", ex.getTargetException());
}
}
实例化之后,代码就开始返回。那么就跟着返回到doCreateBean()的方法这里。那么doCreateBean的第一部分就说完了,那么接下来继续说这个方法的第二部分。
doCreateBean方法的第二部分:解决循环引用。
这一部分主要讲循环引用的问题。这里只是说个介绍,毕竟本文的主线是bean的实例化,上面的方法已经将bean实例化出来了。这里就是做个循环引用的简单介绍,后期会单独再写一篇博客讲。讲完循环引用,然后就是讲下面源码里面的addSingletonFactory()方法。
// 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);
}
});
}
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
可以看到这个方法里,将这个bean加到相关的singletonFactories里和registeredSingletons里。
如下图:存放bean和实例化对象的map:singletonObjects仍然没有实例化的bean,因为在之前实例化出来后,我们还有往map中存放。然通过刚刚的register方法,registeredSingletons这个集合里,已经存放了beanName.
doCreateBean方法的第三部分:初始化bean。
上面是将bean进行了实例化,这里是将实例化的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.");
}
}
}
}
doCreateBean方法的第四部分:register bean as disposablebean。
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
if (mbd.isSingleton()) {
// Register a DisposableBean implementation that performs all destruction
// work for the given bean: DestructionAwareBeanPostProcessors,
// DisposableBean interface, custom destroy method.
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
// A bean with a custom scope...
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
}
}
做完以上的四部,doCreateBean方法就执行完毕了,返回的是我们创建的bean实例。
一直返回到
DefaultSingletonBeanRegistry类里面的public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) 方法。
我们知道,我们的bean已经实例化,并将这个实例化的对象返回,但是还没有存map里。这个时候,返回到getSingleton()方法时候,继续往下执行,就来到下面这个方法:addSingleton()方法。在这个方法里,传入beanName和刚刚实例化出来的对象singletonObject,
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
进入这个存入map的方法,下面这个就是。这个应该属于一看就懂的,就不解释了。
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
到此,实例化的bean就被放在了map类型的singletonObjects中,然后程序就开始返回。
整个流程基本就是这样,欢迎批评指正!