先看下简单的Spring应用
public static void main(String[] args) {
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
TestBean bean = (TestBean)bf.getBean("test");
bean.test();
}
获取bean的时候调用getBean方法,跟踪源码发现最后调用的是doGetBean方法
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
下面我们详细来看下doGetBean方法
获取Bean对象整体流程
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
/*进行beanName转换,有两个原因
*1)bean配置的时候可以配置别名,name可能是别名,需要转换成对应的真实beanName
*2)name可能是以&字符开头的,表明调用者想要获取FactoryBean本身,而非FactoryBean实现类所创建的bean
*/
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
/*
*
* 检查缓存中或者实例工厂中是否有实例对象
*
* 因子在创建单例bean的时候回存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖
* Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光
* 也就是将ObjectFactory加入到缓存中,一旦下个bean创建时需要依赖上个bean则直接使用ObjectFactory
*/
//直接尝试从缓存中获取或者singletonFactories中的ObjectFactory中获取
Object sharedInstance = getSingleton(beanName);
/*
*如果sharedInstance为空,则说明缓存中没有对应的实例,表明这个类还没创建
* BeanFactory并不会在一开始就将所有的单例bean实例化好,而且在调用getBean获取
* bean时再实例化,也即是懒加载
*
* getBean有很多重载方法,在首次获取某个bean时,可以传入用于初始化bean的参数数组(args),BeanFactory会根据这些
* 参数去匹配何时的构造方法构造bean实例。当然,如果单例bean早已创建好,这里的args就没用了
*
*/
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
/*
*如果sharedInstance是普通的单例bean,下面的方法会直接返回
* 但是如果sharedInstance是FactoryBean类型,则需要调用getObject工厂方法获取
* 真正的bean实例。如果用户想要获取FactoryBean本身,这里也不会特别的处理,直接返回即可
*/
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
/*
* 如果上面的条件不满足,则表明sharedInstance可能为空,此时beanName对应的bean实例
* 可能还没创建
* 还有一种可能,如果当前容器有父容器,beanName对应的bean实例可能在父容器中被创建
* 所以在创建实例前,需要先去父容器里检查一下
*/
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
//BeanFactory不缓存Prototype类型的bean,无法处理该类型的循环依赖问题
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
//如果sharedInstance为空,则到父容器中查询bean的实例
BeanFactory parentBeanFactory = getParentBeanFactory();
//如果beanDefinitionMap中也就是在所有已经加载过的类中不包括beanName则尝试从parentFactory中查找
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
//获取name对应的beanName,如果name是以&字符开头,则返回&+beanName
String nameToLookup = originalBeanName(name);
//父容器是AbstractBeanFactory类型,调用父容器的doGetBean方法查找
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
//根据args是否为空,已决定调用父容器哪个方法获取bean
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
//如果不是仅仅做类型检查则是创建bean,这里要进行记录
if (!typeCheckOnly) {
markBeanAsCreated(beanName);//标记当前beanName对应的bean已创建
}
try {
//合并父BeanDefinition和子BeanDefinition
//将存在XML配置文件的GenericBeanDefinition转成RootBeanDefinition,如果指定BeanName是子bean的话同时合并父类的相关属性
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
//获取bean所有的dependsOn,如果有依赖,则先加载依赖的bean
String[] dependsOn = mbd.getDependsOn();
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 {
//先加载依赖的bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
if (mbd.isSingleton()) {
/*
*这里并没有直接调用 createBean 方法创建bean实例,而且通过getSingleton(String,ObjectFactory)方法获取bean实例
* getSingleton(String,ObjectFactory)方法会在内部调用ObjectFactory的getObject()方法创建bean
* 并在创建完成后,将bean放入缓存中
*/
sharedInstance = getSingleton(beanName, () -> {
try {
//创建bean实例
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是FactoryBean类型,则调用工厂方法获取真正的bean实例,否则直接返回bean实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);ge'�
}
//创建Prototype类型的bean实例
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
//创建其他类型的bean实例
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;
}
}
// Check if required type matches the type of the actual bean instance.
//进行类型转换
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.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
beanName转换
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
//处理掉beanName中的&字符
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
/*
* 该方法用于转换别名
*/
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
/**
* 这里采用循环处理的原因是,存在别名指向别名的可能
* <bean id="hello" class="com.df.Hello" />
* <alias name="hello" alias="aliasA" />
* <alias name="aliasA" alias="aliasB" />
* alisaB --> aliasA --> hello
*/
do {
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
在Spring容器中,是按照BeanName和Bean对象一样对应进行存储的,通过beanName可以直接找到对应的bean对象。在配置时,支持别名的方式进行配置。通过别名获取bean时,先找到别名对应的真实BeanName,然后再通过beanName进行查找
从缓存中获取单例bean
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//尝试从缓存中获取单例bean实例
Object singletonObject = this.singletonObjects.get(beanName);
/*
* singletonObject为空,说明还没创建,或者还没有完全创建好
* isSingletonCurrentlyInCreation是判断beanName对应的bean是否正在创建中
* 解决bean之间的循环依赖
*/
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//earlySingletonObjects中获取提前曝光的bean 用于处理循环引用
singletonObject = this.earlySingletonObjects.get(beanName);
// 如果如果 singletonObject = null,且允许提前曝光 bean 实例,则从相应的 ObjectFactory 获取一个原始的(raw)bean(尚未填充属性)
if (singletonObject == null && allowEarlyReference) {
//获取相应的工厂类
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//提前曝光bean实例 ,用于解决循环依赖
singletonObject = singletonFactory.getObject();
//放入缓存中 这样如果其他的bean依赖当前bean,则可以从earlySingletonObjects中获取
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
在Spring中,有很多缓存
singletonObjects:用于存放单例bean对象
earlySingletonObjects:也是用于存放单例bean对象,它用于解决循环依赖
singletonFactories:存放创建bean对象的factoryObject
对于单类对象,由于每次获取的都是同一个对象,为了提供效率,Spring会将这些对象缓存起来。Spring容器中绝大多数对象都是单类的,所以每次调用getBean方法时,首先尝试从缓存中获取对应的bean对象,提高了性能。
对于循环依赖的问题,后面专门会说
从实例中获取bean对象
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
//如果name以&开头,但beanInatance却不是FactoryBean,则认为有问题
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
}
/*
上面判断通过后,表明beanInstance可能是一个普通的bean,也可能是一个FactoryBean
如果是一个普通的bean,这里直接返回beanInstance即可
如果name是以&开头的,则说明用户最终想要获取的是Factory本身,也直接返回
如果是FactoryBean,则要调用工厂方法生成一个实例
*/
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
if (mbd == null) {
/*
如果mbd为空,则从缓存中加载bean。FactoryBean生成的单例bean会被缓存
在factoryBeanObjectCache集合中,不用每次都创建
*/
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
//到了这里,可以保证是FactoryBean类型了
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
//如果mbd为空。则判断是否存在名字为beanName的beanDefine
if (mbd == null && containsBeanDefinition(beanName)) {
//合并BeanDefinition
mbd = getMergedLocalBeanDefinition(beanName);
}
//跟Aop相关,如果被Aop增强了,则为true
//是否是用户定义的而不是应用程序本事定义的
boolean synthetic = (mbd != null && mbd.isSynthetic());
//调用getObjectFromFactoryBean
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
beanInstance只是初始状态的bean,不一定是最终我们想要的bean。如果是FactoryBean类型,beanInstance只是FactoryBean的初始状态,我们正在需要的bean需要调用FactoryBean的factory-method方法来获取
处理加载依赖
在bean配置中,可以通过depends-on属性来配置加载依赖类。此时Srping会优先加载依赖的类,然后再加载当前bean
<bean id="sysinit" class="SystemInit">
<bean id="manager" class="CacheManager" depends-on="sysinit"/>
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
/*
检测是否存在循环依赖,两个bean
*/
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
//注册依赖记录
registerDependentBean(dep, beanName);
try {
//先加载依赖的bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
代码逻辑很简单,从当前bean的定义中获取依赖类,然后注册依赖记录,加载依赖类
根据不同的scope获取bean对象
获取单类bean
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
//全局变量需要同步
synchronized (this.singletonObjects) {
//首先检测beanName对应的bean是否已经加载过,因为singleton模式其实就是复用以创建的bean,所以这一步是必须的
Object singletonObject = this.singletonObjects.get(beanName);
//只有没加载过,才能进行初始化
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while 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 + "'");
}
//创建前的操作 将此beanName加入singletonsCurrentlyInCreation缓存中, 标记此bean正在创建中
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//初始化bean
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
//从singletonsCurrentlyInCreation中删除
afterSingletonCreation(beanName);
}
if (newSingleton) {
//加入到缓存 并删除创建过程中的辅助状态
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
1)首先锁住singletonObjects防止并发操作
2)再次确认对应的bean对象没有创建
3)在创建前标记beanName对应的bean正在创建中,上面从缓存中获取单例的时候,可能会判断
4)然后调用singletonFactory的getObejct方法创建bean对象
5)创建完成之后,从singletonsCurrentlyInCreation中删除beanName
6)如果当前bean是第一次创建对象,则将bean对象加入到单例缓存中
Prototype类型bean的获取
Prototype类型的bean每次获取都会创建一个新的bean对象,代码很简单,就是在对象创建前标记正在创建,创建后删除此标记
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
其他scope类型bean的获取
和Prototype类型bean获取的区别在于会从scope中获取
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);
}
}
}
类型转换
当参数requiredType不为空,且bean对象不是requiredType类型实例时,就会进行类型缓存,requiredType在调用getBean方法时传入,例如:
applicationContext.getBean("test",TestBean.class);
//进行类型转换
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.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}