在【spring 源码】IOC 之 ClassPathXmlApplicationContext 1-5 小段源码里屡次调用了getBean()的方法,咱们常常经过这个方法从beanFactory里获取bean实例,而bean的初始化细节也在这个方法里实现了。本文重点解析getBean()方法。java
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
// L235
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// 从手动注册的单例缓存里取出相关实例在下面的1-0展开细说
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
//建立实例的第一种方式:正在建立的共享单例实例不为空且是无参数的状况(此时的单例对象并无真正实例化完毕,仅仅是提早曝光,解决循环依赖的策略)
...//打印相关日志,略
// 下面这个方法:若是是普通 Bean 的话,直接返回 sharedInstance,
// 若是是 FactoryBean 的话,返回它建立的那个实例对象 详见1-1
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
//建立实例的第二种方式
// 当前线程已经建立过了此 beanName 的 prototype 类型的 bean,那么抛异常.能调用到这里的确定都是单例的
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 检查当前父bean工厂是否存在该bean实例,若是不存在就递归调用直到有实例返回
String nameToLookup = originalBeanName(name);
if (args != null) {
// 有参数,这里不展开详说
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// 无参数建立实例
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
//将beanName放入alreadyCreated,标识其实例已经建立
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
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);
getBean(dep);
}
}
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
//这里是第二种建立bean实例的方式,1-2展开详说
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 = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//非单例状况,忽略
else if (mbd.isPrototype()) {
...
}
else {
...
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
...
}
}
return (T) bean;
}
复制代码
这里的getSingleton()调用了AbstractBeanFactory父类DefaultSingletonBeanRegistry#getSingleton()方法。spring
在此以前咱们先了解一下spring单例的三级缓存缓存
/** 已实例好单例对象缓存 为了方便理解称为一级缓存(下同)*/
private final Map singletonObjects = new ConcurrentHashMap(256);
/** 提早曝光的单例对象缓存(还没有实例完) 二级缓存*/
private final Map earlySingletonObjects = new HashMap(16);
/** 单例对象工厂缓存 三级缓存*/
private final Map> singletonFactories = new HashMap>(16);
复制代码
DefaultSingletonBeanRegistry.java L172安全
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
/**
* Return the (raw) singleton object registered under the given name.
* Checks already instantiated singletons and also allows for an early
* reference to a currently created singleton (resolving a circular reference).
* 大致意思是:返回一个以给定名称注册的单例对象,检查已经实例好的单例池子,同时也容许对当前对象的引用
*/
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//单例对象的cache
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//一级缓存里没有该对象而且此beanName正在建立过程当中才会进来,由于正在建立的bean也许会在二级缓存里
synchronized (this.singletonObjects) {
//二级缓存中取
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//若是二级缓存里没有就从三级缓存里取
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//三级缓存里不为空就将其放入二级缓存里,并将其从三级缓存里移除
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
复制代码
到这里已经把spring 单例的三级缓存说完了,这三个缓存是spring处理循环依赖的重要依据,有兴趣的话能够看我以前的文章《spring是如何解决循环依赖的?》。bash
AbstractBeanFactory#getObjectForBeanInstance() L1607app
/**
* Get the object for the given bean instance, either the bean
* instance itself or its created object in case of a FactoryBean.
* 下面这个方法:若是是普通 Bean 的话,直接返回 sharedInstance,
* 若是是 FactoryBean 的话,返回它建立的那个实例对象
*/
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
//若是这个bean不是工厂bean,直接抛异常,不让其调用者撤销引用工厂
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
//name以&开头而且bean实例不属于工厂bean,直接抛异常
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, //unless the caller actually wants a reference to the factory. if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { //①若是bean实例不是工厂bean,名称是以&开头,直接放回bean实例 //②若是bean实例是工厂bean,名称不是以&开头,直接放回bean实例 return beanInstance; } Object object = null; if (mbd == null) { //从factoryBeanObjectCache缓存里取 object = getCachedObjectForFactoryBean(beanName); } if (object == null) { // Return bean instance from factory. FactoryBean<?> factory = (FactoryBean<?>) beanInstance; if (mbd == null && containsBeanDefinition(beanName)) { //将该类的子类、父类配置信息都集中到rootBeanDefinition里 mbd = getMergedLocalBeanDefinition(beanName); } boolean synthetic = (mbd != null && mbd.isSynthetic()); //下面调用了FactoryBeanRegistrySupport类的getObjectFromFactoryBean(),是从factoryBean里获取bean实例的入口 object = getObjectFromFactoryBean(factory, beanName,!synthetic); } return object; } 复制代码
FactoryBeanRegistrySupport#getObjectFromFactoryBean() L98less
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
//单例场景
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
//这里是实例化bean的最核心入口
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (object != null && shouldPostProcess) {
try {
//这里会调用全部BeanPostProcessor#postProcessAfterInitialization的实现方法,这里不作展开,后续会有文章介绍
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
}
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
}
}
return (object != NULL_OBJECT ? object : null);
}
}
else {
//非单例场景,这里不作展开
...
return object;
}
}
复制代码
FactoryBeanRegistrySupport#doGetObjectFromFactoryBean() L148ide
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
//调用java的安全模型来实例化相关类,保证安全
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
return factory.getObject();
}
}, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
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 && isSingletonCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException( beanName, "FactoryBean which is currently in creation returned null from getObject"); } return object; } 复制代码
这里只简单说一下,后面会有专门一篇文章详细介绍java的安全模型,感兴趣的同窗能够先参考《Java 受权内幕》,Java 安全模型介绍》,《Java安全——安全管理器、访问控制器和类装载器》先了解一下java的安全模型。post
小结一下,到这里整个1-1第一种建立bean实例的方法结束了,接下来继续回到AbstractBeanFactory#doGetBean()方法继续往下看。ui
//AbstractAutowireCapableBeanFactory#createBean() L447
/**
* Central method of this class: creates a bean instance,
* populates the bean instance, applies post-processors, etc.
* @see #doCreateBean
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
...
RootBeanDefinition mbdToUse = mbd;
//经过反射获取指定beanName的类的字节码,并将其赋值给mbdToUse的属性
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
//检查类的方法有无重写,没有重写的设置AbstractBeanDefinition里Overloaded为false,避免后续的类型检查的开销
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
...
}
try {
// 若是重写并注册了BeanPostProcessor,在建立类以前生成类的代理并执行BeanPostProcessor的postProcessAfterInitialization()
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
...
}
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
...
}
return beanInstance;
}
复制代码