回顾
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
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;
}
});
//该方法是FactoryBean接口的调用入口
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
前面我们已经跟了 getSingleton 和 createBean 方法。知道这里已经拿到了 Bean 实例,那么为什么还要下面这一步呢?
因为还有这种 Bean:
@Component
public class FactoryBeanDemo implements FactoryBean {
@Override
public Object getObject() throws Exception {
return new FactoryB();
}
@Override
public Class<?> getObjectType() {
return FactoryB.class;
}
}
如果是实现了 FactoryBean,我们要拿到的实例应该是它 getObject() 后的结果 FactoryB。当然,我们也可以就想拿到 FactoryBeanDemo。为了处理这一层逻辑,有了本节要讲的 getObjectForBeanInstance 方法。
重点
如果实例不是 FactoryBean 类型的,或者name是以&号开头的,则直接返回实例。
也就是说你不想拿到 FactoryBean 通过 getObject() 得到的对象,而是它本身,你需要在它的名字前面加个 “&” 符号
跟源码
类 AbstractBeanFactory
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
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.
//如果实例不是FactoryBean类型的,或者name是以&号开头的,则直接返回实例。见 1.4.3.1
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
//如果代码能走下来,则说明 beanName不是以&开头,并且beanInstance是FactoryBean类型的
Object object = null;
if (mbd == null) {
//从缓存里面拿FactoryBean类型的实例
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
//重点看 见1.4.3.2
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
1.4.3.1 isFactoryDereference
类 BeanFactoryUtils
public static boolean isFactoryDereference(@Nullable String name) {
return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
}
1.4.3.2 getObjectFromFactoryBean
类 FactoryBeanRegistrySupport
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) {
//调用getObject方法
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 (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)) {
//把实例缓存到factoryBeanObjectCache map中,这个是单独缓存FactoryBean类型实例的map
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;
}
}
跟 doGetObjectFromFactoryBean:
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方法
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;
}
跟 getObject:
类 MapperFactoryBean
@Override
public T getObject() throws Exception {
return getSqlSession().getMapper(this.mapperInterface);
}
可以看到,这就是为什么在用 Mybatis 时,调用 Mapper 接口能访问方法了。其实,在 Spring 容器启动过程中,早就创建了动态代理。
详见:
Mybatis 的初始化与建造者模式
面试官:为什么使用 Mapper 接口就能对数据库进行访问?
SpringBoot 整合 Mybatis 源码阅读(2.3.1.RELEASE)
3591

被折叠的 条评论
为什么被折叠?



