上一節梳理了一下BeanDefinition的合併過程,而且講到BeanDefinition中的基本屬性
@Nullable
private volatile Object beanClass;
beanClass屬性描述的是Bean的類型,而且很特殊的設置爲Object類型,java中萬物皆是對象,但是我們在讀取xml或者propeties時,賦值的是什麼類型呢,斷點調試發現是Sting類型的對象,
但是在執行過getBean方法之後,會調用上一節的mergeBeanDefinition方法,這個時候的beanFactory中有屬性:mergedBeanDefinitions,其中的user的beanDefinition中的beanClass是Class對象
其中到底發生了什麼?
在mergeBeanDefinition之後,bean的屬性已經全部被準備完畢,那麼createBean中的時候有個方法,把beanClass的轉換完成:
/ 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);
具體的實現方法
@Nullable
protected Class<?> resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch)
throws CannotLoadBeanClassException {
try {
if (mbd.hasBeanClass()) {
return mbd.getBeanClass();
}
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
}
else {
return doResolveBeanClass(mbd, typesToMatch);
}
}
catch (PrivilegedActionException pae) {
ClassNotFoundException ex = (ClassNotFoundException) pae.getException();
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
}
catch (ClassNotFoundException ex) {
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
}
catch (LinkageError err) {
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
}
}
1:首先會校驗mbd.hasBeanClass()這個方法校驗了beanClass是否爲Class對象,如果不是,繼續,
2:會校驗java安全是否開啓
3:解析beanClass
第三步的過程很奇妙
會調用BeanDefinition中的方法:
/**
* Determine the class of the wrapped bean, resolving it from a
* specified class name if necessary. Will also reload a specified
* Class from its name when called with the bean class already resolved.
* @param classLoader the ClassLoader to use for resolving a (potential) class name
* @return the resolved bean class
* @throws ClassNotFoundException if the class name could be resolved
*/
@Nullable
public Class<?> resolveBeanClass(@Nullable ClassLoader classLoader) throws ClassNotFoundException {
String className = getBeanClassName();
if (className == null) {
return null;
}
Class<?> resolvedClass = ClassUtils.forName(className, classLoader);
this.beanClass = resolvedClass;
return resolvedClass;
}
利用Spring的工具類 ClassUtils方法獲取resolvedClass;
classLoader是獲取的BeanFactory中的AppClassLoader
ClassUtils中的方法實現
try {
return Class.forName(name, false, clToUse);
} catch (ClassNotFoundException var9) {
int lastDotIndex = name.lastIndexOf(46);
if (lastDotIndex != -1) {
String innerClassName = name.substring(0, lastDotIndex) + '$' + name.substring(lastDotIndex + 1);
try {
return Class.forName(innerClassName, false, clToUse);
} catch (ClassNotFoundException var8) {
;
}
}
是調用了java.lang中的Class.forName方法。這個時候,就完成了String類型到Class類型的轉換。