MapperFactoryBean 是个啥?
- MapperFactoryBean 是 实现了 FactoryBean 的工厂bean.
- 你日常调用的 dao 层接口就是 MapperFactoryBean实例化的.
为啥dao接口能够执行,我们都知道接口是不能实例化的,答案只有一个mybatis帮你 代理了 dao 接口
看下MapperFactoryBean的结构

看下MapperFactoryBean的属性(包含父类的属性)
MapperFactoryBean
Class<T> mapperInterface
boolean addToConfig = true
SqlSession sqlSession
boolean externalSqlSession
FactoryBean
- FactoryBean 是spring 提供的一个顶层接口
- 实现了FactoryBean的bean比较特殊,getBean("xxx") 获取的是当前bean 的getObject() 的返回,getBean("&xxx") 才是当前工厂bean
看下spring 获取 factoryBean 的入口
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(String, Class, Object[], boolean) 方法片段,spring不懂的可以看下我以前的文章
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// Create bean instance.
if (mbd.isSingleton()) {
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;
}
});
//处理 FactoryBean 返回bean
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
}
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
...................................................
// 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 不包含 & 才能继续走下去
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
if (mbd == null) {
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());
//这里
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
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) {
//这里
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;
}
..........................................
return object;
}
}
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 {
//这里 调用了 factory的getObject方法
object = factory.getObject();
}
}
//好了 我们直接看下 mapperFactortBean 的 getObject
//看到这里 我们应该都知道了 dao 层 接口是被代理了
@Override
//我们的dao层接口实例化从这里开始
public T getObject() throws Exception {
//这个地方两个方法,都有必要看下
return getSqlSession().getMapper(this.mapperInterface);
}
//好吧,我们看到了直接返回的是当前 mapperFactoryBean的 sqlSession
//你以为就这么简单的结束了,并不是,你有没有想过这个 sqlSession 是哪里来的
public SqlSession getSqlSession() {
return this.sqlSession;
}
//我观察了下有两个方法给sqlSession 赋值的,如下:
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
if (!this.externalSqlSession) {
this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
}
}
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSession = sqlSessionTemplate;
this.externalSqlSession = true;
}
//看了上面的两个方法我总结出来 sqlSession 就是 sqlSessionTemplate
//sqlSessionTemplate 是由 sqlSessionFactory 创建的,知道为啥要先讲 sqlSessionFactory了吧
//那好吧,上面的方法是啥时候被调用的呢
//这个地方 在 @MapperScan 文章中说了 , mybatis 把我们的mapperFactorBean 的依赖注入模式改为了AUTOWIRE_BY_TYPE'
//这个依赖注入的模式 意味着 我们的bena 只需要 存在 set 方法 就会调用,所有上面的两个方法都会调用(我真的很佩服自己)
//然后 SqlSessionFactory 讲过了,SqlSessionTemplate 也是在 mybatisAutoConfig 中@Bean 创建的
//看下 sqlSession(应该说是sqlSesisonTemplate) 的getMapper 方法究竟干了什么
@Override
public <T> T getMapper(Class<T> type) {
//获取 configuration 这个 configuration就是 sqlSessionFactory 里面的 configuration
return getConfiguration().getMapper(type, this);
}
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession);
}
@SuppressWarnings("unchecked")
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
//获取 mapperProxyFactory 这个东西 是在创建 sqlSessionFactory 时候放入的
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
//这里
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
public T newInstance(SqlSession sqlSession) {
// 这里, MapperProxy 是 实现了InvocationHandler 的接口,看到这里,应该可以猜到,是使用的 jdk 的动态代理
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
//结束
@SuppressWarnings("unchecked")
protected T newInstance(MapperProxy<T> mapperProxy) {
//返回了代理对象
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}