今天开门见山,直接亮代码~
MyTestBean bean = (MyTestBean)bf.getBean("myTestBean")
我想上面这行代码,第一次接触过spring这个框架时都应该接触过;读取xml中我们配置的bean;
spring分为7大部分组成,有一个部分叫做:SpringBean;
为了知道这句代码实现了什么样的功能,看官可以可以打开你的开发工具,找到下面这张图的几个包;
首先打开AbstractBeanFactory 这个类, 找到 getBean 这个方法:
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
进入doGetBean :
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
//把beanName 前面可能存在的 所有符号 全部取出;
final String beanName = transformedBeanName(name);
Object bean;
/**
* spring会先检查缓存中或者实例工厂中是否有对应的实例,因为在创建单例bean的时候回存在医疗注入的情况;
* 而在创建以来的时候为了避免循环依赖,spring创建bean的原则是不等bean创建完成就会将创建bean的 objectfactory提前曝光,
* 也就是将objectFactory加入到缓存中,一旦下一个bean创建的时候需要依赖上个bean则直接使用objectfactory;
*/
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
循环依赖是什么意思呢? 如果存在 A中有B的属性,B中又有A的属性,那么当依赖注入的时候,就会产生A还未完成创建的时候又去创建B,又再次返回创建A;
进入 getSingleton(beanName) 方法 会跳到 DefaultSingletonBeanRegistry 这个类的
再次进入 getSingleton(beanName, true )这个方法;
进入这个方法之前,先了解一个概念,单例在spring的同一个容器中只会被创建一个,之后获取bean就可以直接冲单例的缓存中获取了;
下面介绍的就是从缓存中获取bean的情况;
这样就返回了单例的 singletonObject
看到这里,你可能不知道 singletonFactory怎么来的, 进入 singletonFactories 这个 引用去看看:
/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);
/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory> singletonFactories = new HashMap<String, ObjectFactory>(16);
/** Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
/** Set of registered singletons, containing the bean names in registration order */
private final Set<String> registeredSingletons = new LinkedHashSet<String>(64);
1.singletonObjects : 用于保存beanName和创建bean实例之间的关系
2.singletonFactories : 用于保存beanName和创建bean的工厂之间的关系
3.earlySingletonObjects :也是保存beanName和bean实例之间的关系,与singletonObjects 的不同之处在于,当一个单例bean被放在这里后,那么当bean还在创建过程中,就可以通过getBean的方法获取了,其目的是用来检测循环引用。
4.registeredSingletons : 用于保存当前所有已注册的bean。
因为 singletonFactory实现了 ObjectFactory这个接口; spring全家桶 会根据 beanName去创建 一个singletonFactory;
上面是从缓冲中获取单例,那么缓冲中要是不存在已经加载好的单例bean,那就要重头开始执行加载bean了,spring重写了getSingleton,
public Object getSingleton ( String beanName, ObjectFactory singletonFactory) { ...... }
从上面代码可以看到,spring依赖注入时,使用了双重判断加锁的单例模式,首先从缓存中获取bean实例,如果为null,对缓存map加锁,然后再从缓存中获取bean,如果继续为null,就创建一个bean。这样双重判断,能够避免在加锁的瞬间,有其他依赖注入引发bean实例的创建,从而造成重复创建的结果。
Spring并没有使用我们常见的私有构造方法来创建bean,而是通过singletonFactory.getObject()返回具体beanName对应的ObjectFactory来创建bean。
这就是spring获取bean的一个简单流程;创建了spring的bean对象,还没完,还没有实例化这个bean。 且听下回分解~