//xml配置文件的解析
ClassPathResource resource = new ClassPathResource("spring.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
//bean的加载,这篇文章就是讲解这一句代码
MyTestBean myTestBean = (MyTestBean) beanFactory.getBean("myTestBean");
System.out.println(myTestBean.getTestStr());
通过跟踪AbstractBeanFactory类的getBean(String name);
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
找到实际加载函数是doGetBean()方法
去掉干扰代码,只看主要代码
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//1.转换对应的beanName
final String beanName = transformedBeanName(name);
Object bean;
//2. 直接从三级缓存(单例对象、单例提前曝光的对象、单例对象工厂)中获取bean实例
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
//3.返回bean,有时候并不是直接返回实例本身,而是返回指定方法返回的实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 4. 原型模式的依赖检查,例如A还未创建完成的时候 因为B的创建 再次创建A,就会造成循环依赖
//当isPrototypeCurrentlyInCreation=true时,也就是说当前bean正在创建中,也就时说明存在循环依赖
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
//5.如果beanDefinitionMap中也就是所有已经加载的类中不包括beanName则尝试从parentBeanFactory中查找
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// // 如果没有,查询父工厂
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// // 执行带有args参数的getbean方法
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// 如果没有参数,执行标准的getbean方法
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
//如果不仅仅是做类型检查,那么需要标记此Bean正在创建之中
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 6.将存储xml的GernericBeanDefinition转换为RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//如果beanName对应的类是子类的话,则会合并父类的相关属性
checkMergedBeanDefinition(mbd, beanName, args);
// 7. 获取依赖的Bean
String[] dependsOn = mbd.getDependsOn();
//若存在依赖则递归实例化依赖的bean
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
//8.针对不同的scope进行bean的创建
// 创建单例bean
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
//把当前的beanName加入正在创建beanName的集合中,会在第一步判断
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
//把当前的beanName从正在创建beanName的集合中移除
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 9.检查类型,如果不满足可以进行类型转换,如果转换器进行不了这两种类型的转换,则抛出异常
//将bean转换成requiredType所指定的类型
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
从上面源码中可以看到,bean的加载主要是这九步。下面就会一步一步的讲解这九步。我们可以先不要深究这个方法中的代码,先从整体了解一下这个方法的主题结构。
实现方法: transformedBeanName(name)
返回值:真实的beanName
方法说明:doGetBean方法传入的name,可能并不是beanName,也可能是别名或者是FactoryBean,如果是别名alias,则需要找到对应的beanName;如果是FactoryBean,则需要去除name中&符。
实现方法: getSingleton(beanName);
返回值:beanName对应的单例对象sharedInstance
方法说明:单例在spring同一容器中只会被创建一次,后续直接就从单例缓存中获取。
下面是该方法源码:
DefaultSingletonBeanRegistry.java
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//1.从单例缓存中获取实例
Object singletonObject = this.singletonObjects.get(beanName);
//isSingletonCurrentlyInCreation判断此单例是否正在创建
//检查这个bean是不是null,并且这个bean正在创建中的bean的map缓存(singletonsCurrentlyInCreation)中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//走到这里证明,bean不在单例缓存中,而且有程序在创建beanName
//则锁住单例缓存
synchronized (this.singletonObjects) {
// 2.从提前暴光的单例对象缓存中获取 bean
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 都没有
// 3.从单例工厂的缓存中找到对应的单例工厂生产提前暴光的单例
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//生产单例bean
singletonObject = singletonFactory.getObject();
//添加提前暴光的单例的缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
//移除对应bean工厂
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
代码 中的注释已经很详细了,不在赘述。
值得一说的是,为什么要这么多层缓存?其实是为了检测是否涉及循环依赖。
singletonObjects:用于保存BeanName和创建的bean实例,是个Map对象。
singletonFactories:用户保存beanName和创建bean的工厂,是个Map对象。
earlySingletonObjects:用户保存beanName和创建的bean实例,与singletonObjects不同的是,这里面放的bean还在创建中,可以通过getBean()方法获取到bean,目的是用来检测循环依赖。
实现方法:getObjectForBeanInstance(sharedInstance, name, beanName, null);
返回值:真正想要返回的bean
方法说明:从缓存中或者createBean()获取的都是bean的原始状态,此方法就是对bean进行实例化。需要强调的是,最原始的bean并不一定是我们真正想要的bean。例如,像要factory-method方法返回的bean.
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 若name传递的是如“&student”(以&为前缀)
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
//该bean不是FactoryBean,抛出异常
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}
// 如果beanInstance不是FactoryBean,是一个普通的Bean,直接返回
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
if (mbd == null) {
//根据beanName从缓存中加载bean,注意此处的beanName是包含‘&’符
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
//到这里已经明确知道beanInstance是FactoryBean类型了
// 从工厂中返回bean实例
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// 判断已加载的类中是否定义beanname
if (mbd == null && containsBeanDefinition(beanName)) {
//如果对应的bean是子bean的话,则合并父类的相关属性
mbd = getMergedLocalBeanDefinition(beanName);
}
//是否是用户生成的:判断是用户生成还是应用程序生成
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
FactoryBeanRegistrySupport.java
/** FactoryBean 创建的单例对象的缓存: FactoryBean name --> object */
private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);
protected Object getCachedObjectForFactoryBean(String beanName) {
return this.factoryBeanObjectCache.get(beanName);
}
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
// 从缓存中获取,factoryBeanObjectCache存放
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 缓存中获取不到,从factory中获取
object = doGetObjectFromFactoryBean(factory, beanName);
// 有可能当执行doGetObjectFromFactoryBean函数时,Bean正在创建,所以此时再获取一下
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
beforeSingletonCreation(beanName);
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
从上门代码可以知道主要创建bean实例的代码在doGetObjectFromFactoryBean(factory, beanName);方法中,我们继续追踪到此方法:
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((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
//getObject()方法在实现FactoryBean接口时实现的
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) {
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
return object;
}
上面这么多的代码其实真正逻辑没有几行,在doGetObjectFromFactoryBean方法中我们终于看到了factory.getObject();创建FactoryBean实例的代码。这一逻辑到此也结束了。
说明:只有在单例情况下才会尝试解决循环依赖。
说明:因为bean的初始化过程中很可能用到某些属性,而这些属性很可能是动态配置的。所以要先加载依赖的bean.
scope的类型:基本作用域(singleton、prototype),Web 作用域(reqeust、session、globalsession),自定义作用域。
说明:从doGetBean()方法中知道对不同的scope,创建bean的逻辑都封装在createBean()方法中,下面就去看一看这个方法。
这里太长了,会专门也一篇文章spring源码:bean的创建
把bean转换成参数requiredType类型的。