1 前言
本节我们续前两节(调试查看Mapper接口生成过程、源码分析 Mapper生成注入入口分析)的内容,看下 MapperFactoryBean 是如何代理掉我们的 @Mapper 接口的。
上节我们看到我们的 Mapper 接口的 BeanDefinition, 已经放进 spring 的上下文中了,也就是在 BeanFactory 的 BeanDefinitionMap 里了哈。它的形式是 FactoryBean 的,这时当我们的 Service 或者某个 Bean 有依赖于我们的 Mapper 接口,这时候就会创建 Bean,或者没有任何 Bean 依赖 Mapper 的情况下,因为 BeanDefinition 的 lazyInit 为 false,所以 spring 也会在刷新完上下文的最后面,把所有非懒加载的单例的 Bean 都给创建出来。
所以不管有没有依赖,我们每个 Mapper 的 BeanDefinition 都会创建 Bean,那我们就一步步来看看创建过程。这就涉及到 Bean 的生命周期咯。
还有大家放心看,我都是一步一步调试边理解边思考然后才写的哈,就这节我都调试了不下一百次。
2 源码分析
2.1 找入口
从哪看起呢?我有个 Service 是依赖 Mapper 的:
所以我就在 BeanFactory 的 doGetBean 打了个断点:
它从哪来呢?应该是从创建 Service 的时候,populateBean 发现它的属性依赖,进行 Bean的装配来的,看 debug 来源确实是这样。
所以我们就从 BeanFactory 的 doGetBean() 开始看起吧。顺便复习下 FactoryBean 形式的创建过程哈。
2.2 源码分析
我就拿我这个 accountMapper 来看哈,我们进入到 doGetBean(),来看看 accountMapper 的创建:
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { // 转换 Bean 的名字,主要是当获取 FactoryBean 本身的时候 &开头的处理,这里可以不用管 我们这里 name = accountMapper String beanName = this.transformedBeanName(name); // 我们第一次来获取 此时为空 Object sharedInstance = this.getSingleton(beanName); Object bean; if (sharedInstance != null && args == null) { ... } else { // false if (this.isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } ... if (!typeCheckOnly) { this.markBeanAsCreated(beanName); } try { // 获取 BeanDefinition 这个获取的是 AccoutMapper 的 BeanDefinition 加工后的 MapperFactoryBean 类型的 BeanDefinition 哈 RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName); this.checkMergedBeanDefinition(mbd, beanName, args); String[] dependsOn = mbd.getDependsOn(); String[] var11; // 无 dependsOn 依赖 略过 if (dependsOn != null) { ... } // 是单例的进来 if (mbd.isSingleton()) { sharedInstance = this.getSingleton(beanName, () -> { try { // 进来创建 Bean --注意我们这里创建出来的 bean 是 MapperFactoryBean 对象 return this.createBean(beanName, mbd, args); } catch (BeansException var5) { this.destroySingleton(beanName); throw var5; } }); // 这里如果是普通 Bean 则返回自身,如果是 FactoryBean 则调用 FactoryBean 的 getObject() 方法进行对象的创建哈 // 那我们这里就是调用 MapperFactoryBean 的 getObject() 方法来创建我们的 Mapper 的代理对象哈 bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { ... } else { ... } } catch (BeansException var26) { this.cleanupAfterBeanCreationFailure(beanName); throw var26; } } ... }
好,那我们这里就重点看两部分:
(1)createBean()方法中 MapperFactoryBean 对象的创建过程
(2)getObjectForBeanInstance()方法中,MapperFactoryBean 创建 Mapper 代理对象的过程
2.2.1 MapperFactoryBean 对象创建过程
那我们继续看 createBean(),看看创建过程:
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { RootBeanDefinition mbdToUse = mbd; // resolvedClass 即 MapperFactoryBean.class Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]); ... Object beanInstance; try { // 执行相关后置处理器 beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse); if (beanInstance != null) { return beanInstance; } } catch (Throwable var10) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var10); } try { // 创建 Bean beanInstance = this.doCreateBean(beanName, mbdToUse, args); if (this.logger.isTraceEnabled()) { this.logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (ImplicitlyAppearedSingletonException | BeanCreationException var7) { throw var7; } catch (Throwable var8) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", var8); } }
这里边没什么特别的处理,主要是执行后置处理器,然后我们继续看 doCreateBean()方法:
// beanName 就是 accountMapper mbd 就是 Bean定义信息 protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { BeanWrapper instanceWrapper = null; // 是单例的 if (mbd.isSingleton()) { // 先从缓存中拿,这里要注意了,你会发现它有值?纳闷不?咦什么时候创建的呢?它哪来的? instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName); } // 是空的话,进行创建 if (instanceWrapper == null) { instanceWrapper = this.createBeanInstance(beanName, mbd, args); } Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // 执行后置处理器 synchronized(mbd.postProcessingLock) { if (!mbd.postProcessed) { try { this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable var17) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17); } mbd.postProcessed = true; } } ... Object exposedObject = bean; try { // 属性填充 this.populateBean(beanName, mbd, instanceWrapper); // 初始化 exposedObject = this.initializeBean(beanName, exposedObject, mbd); } catch (Throwable var18) { if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) { throw (BeanCreationException)var18; } throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18); } ... }
我们熟悉的 doCreateBean,最重要的三步,实例化对象、属性填充、初始化。
我在调试还发现一个疑问,就是我是第一次获取 accoutMapper,怎么从 factoryBeanInstanceCache 这个缓存中获取的居然不是空值呢?它又是什么时候进去的呢?
这个问题暂时保留下,因为我还没理解透彻,只是大概估计是它来源于 BeanFactory 的 allowFacoryBeanInit,所以提前把 FactoryBean 类型的对象提前创建出来,放进了 factoryBeanInstanceCache 缓存里。
想一个问题,我们的 Mapper 接口肯定有多个,它都是从 MapperFactoryBean 对象创建出来的,那么这些 MapperFactoryBean 对象是用的同一个?还是各是各的?
从结果上来看,每个 Mapper 接口都有各自的 MapperFactoryBean 对象。
它的实例化,会提前创建好,放进 factoryBeanInstanceCache 缓存里,它的 key 是每个 mapper 接口的 bean 名字,如我的 accountMapper、userMapper哈。
接下来MapperFactoryBean 的属性填充,这里你就会发现有一个小问题或者小细节。
如果你调试的话或者在看后续 MapperFactoryBean 的getObject()方法里,会根据 sqlSessionTemplate来创建,那么对象里的 sqlSessionTemplate 什么时候有值的呢?或者会发现在创建的过程中,会伴随着 SqlSessionFactory 、MybatisProperties、MybatisAutoConfiguration SqlSessionTemplate 的创建等,你还会发现创建完,咦它的sqlSessionTemplate 怎么就有值了呢?
大概能猜到是属性填充进来的,那么我看一下 MapperFacoryBean 构造器也没有它,也没有装配,倒是有几个 set 方法:
// mapperFactoryBean 继承了 SqlSessionDaoSupport public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {} public abstract class SqlSessionDaoSupport extends DaoSupport { private SqlSessionTemplate sqlSessionTemplate; public SqlSessionDaoSupport() { } // 设置 sqlSessionFactory public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { if (this.sqlSessionTemplate == null || sqlSessionFactory != this.sqlSessionTemplate.getSqlSessionFactory()) { this.sqlSessionTemplate = this.createSqlSessionTemplate(sqlSessionFactory); } } protected SqlSessionTemplate createSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } public final SqlSessionFactory getSqlSessionFactory() { return this.sqlSessionTemplate != null ? this.sqlSessionTemplate.getSqlSessionFactory() : null; } // 设置 sqlsessionTemplate public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { this.sqlSessionTemplate = sqlSessionTemplate; } }嘿嘿,其实来源于它的 BeanDefinition,也是我上节没注意到的一个细节:
definition.setAutowireMode(2);就是这个装配模式,他会根据你类里的 set 方法,来进行设置。我们这里复习下这个装配模式类型:
Autowiring mode:表示自动装配的模式,用一个整形变量来表示
0:表示 no(不装配)
1:表示 byName(按名称装配)根据类的属性字段进行填充
2:表示 byType(按类型装配) 根据 set 方法进行填充
3:表示 constructor(根据构造函数装配) 构造器的填充好啦。
初始化就跟正常的 Bean 一样了,我这里最后把整个过程画个图捋一下:
2.2.2 MapperFactoryBean 创建 Mapper 代理过程
我们接着 2.2.1 的 getObjectForBeanInstance()方法看起:
// beanInstance 此时是 MapperFactoryBean 对象 name = beanName = accountMapper protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { // 不是 & 开头 不获取 FactoryBean 对象本身 if (BeanFactoryUtils.isFactoryDereference(name)) { if (beanInstance instanceof NullBean) { return beanInstance; } else if (!(beanInstance instanceof FactoryBean)) { throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass()); } else { if (mbd != null) { mbd.isFactoryBean = true; } return beanInstance; } } else if (!(beanInstance instanceof FactoryBean)) { return beanInstance; } else { // 走到这里 Object object = null; if (mbd != null) { mbd.isFactoryBean = true; } else { // 第一次缓存中获取为空 object = this.getCachedObjectForFactoryBean(beanName); } if (object == null) { FactoryBean<?> factory = (FactoryBean)beanInstance; if (mbd == null && this.containsBeanDefinition(beanName)) { mbd = this.getMergedLocalBeanDefinition(beanName); } // getObjectFromFactoryBean 创建 boolean synthetic = mbd != null && mbd.isSynthetic(); object = this.getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; } }
继续 getObjectFromFactoryBean() 方法:
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) { if (factory.isSingleton() && this.containsSingleton(beanName)) { synchronized(this.getSingletonMutex()) { Object object = this.factoryBeanObjectCache.get(beanName); if (object == null) { object = this.doGetObjectFromFactoryBean(factory, beanName); Object alreadyThere = this.factoryBeanObjectCache.get(beanName); if (alreadyThere != null) { object = alreadyThere; } else { if (shouldPostProcess) { if (this.isSingletonCurrentlyInCreation(beanName)) { return object; } this.beforeSingletonCreation(beanName); try { object = this.postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable var14) { throw new BeanCreationException(beanName, "Post-processing of FactoryBean's singleton object failed", } finally { this.afterSingletonCreation(beanName); } } if (this.containsSingleton(beanName)) { this.factoryBeanObjectCache.put(beanName, object); } } } return object; } } else { Object object = this.doGetObjectFromFactoryBean(factory, beanName); if (shouldPostProcess) { try { object = this.postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable var17) { throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", var17); } } return object; } }
不用细看,最后落点都是 doGetObjectFromFactoryBean 这个方法:
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException { Object object; try { if (System.getSecurityManager() != null) { AccessControlContext acc = this.getAccessControlContext(); try { object = AccessController.doPrivileged(factory::getObject, acc); } catch (PrivilegedActionException var6) { throw var6.getException(); } } else { // 找到我们熟悉的字眼,就是它 getObject() object = factory.getObject(); } } catch (FactoryBeanNotInitializedException var7) { throw new BeanCurrentlyInCreationException(beanName, var7.toString()); } catch (Throwable var8) { throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", var8); } if (object == null) { if (this.isSingletonCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName, "FactoryBean which is currently in creation returned null from getObject"); } object = new NullBean(); } return object; }
嘿嘿,终于到我们的 MapperFactoryBean 对象的 getObject()方法了:
// MapperFactoryBean public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> { public SqlSession getSqlSession() { return this.sqlSessionTemplate; } public T getObject() throws Exception { // getSqlSession()就是拿到2.2.1里设置的 sqlSessionTemplate return this.getSqlSession().getMapper(this.mapperInterface); } } // SqlSessionTemplate public class SqlSessionTemplate implements SqlSession, DisposableBean { // 最后就是通过 configuration 里获取的,这就跟我之前的文章衔接上了哈 public <T> T getMapper(Class<T> type) { return this.getConfiguration().getMapper(type, this); } }
然后我们进入 Configuration 看看代理的创建:
// Configuration public class Configuration { public <T> T getMapper(Class<T> type, SqlSession sqlSession) { // 交给内部的 mapperRegistry 创建 return this.mapperRegistry.getMapper(type, sqlSession); } } // MapperRegistry public class MapperRegistry { private final Configuration config; private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap(); public MapperRegistry(Configuration config) { this.config = config; } // 创建 Mapper 代理 public <T> T getMapper(Class<T> type, SqlSession sqlSession) { MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type); if (mapperProxyFactory == null) { throw new BindingException("Type " + type + " is not known to the MapperRegistry."); } else { try { // 交给工厂创建 return mapperProxyFactory.newInstance(sqlSession); } catch (Exception var5) { throw new BindingException("Error getting mapper instance. Cause: " + var5, var5); } } } } // MapperProxyFactory 工厂 public class MapperProxyFactory<T> { protected T newInstance(MapperProxy<T> mapperProxy) { // JDK代理方式创建 return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy); } public T newInstance(SqlSession sqlSession) { // MapperProxy 增强器 MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache); return this.newInstance(mapperProxy); } }
顺着上一个图,我们完善下整个过程:
3 小结
好啦,本节我们主要看了 MapperFactoryBean 对象的创建过程,以及创建 Mapper 代理的过程(到configuration截至)。有一个重要的小细节也是上节没注意到的 BeanDefinition 的 autowirwMode = 2,根据方法的注入设置 SqlSessionTemplate 属性值哈。有理解不对的地方欢迎指正。
标签:Mapper,object,MapperFactoryBean,mbd,创建,beanName,源码,null From: https://www.cnblogs.com/kukuxjx/p/18047342