在前面两篇博客中分别介绍了系统是如何将定义的接口Mapper接口注册《Mapper接口的注册》到系统中,系统又是如何绑定接口类名与用来生成接口的MapperFactoryBean之间的关系《接口代理工厂类注册》。
本篇博客将分析系统是如何根据调用时传入的beanName找到接口的动态代理对象的。关于测试代码中的配置文件就不贴出来的,在前面几遍关于mybatis的博客中已经贴出了。
在注册Mapper接口的beanDefinition的时候,beanName为cityMapper,而beanClass为MapperFactoryBean。直接看获取Bean实体的代码:
AbstractBeanFactory:
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// 在获取Mapper接口的代理实体时,beanName和name均是cityMapper
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
//这里获取的sharedInstance是不等于空的
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//直接执行的是下面的方法
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
......
// 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.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
AbstractAutowireCapableBeanFactory:
@Override
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
//添加bean直接的依赖,接口bean没有依赖其他的bean,会直接调用父类的getObjectForBeanInstance方法
String currentlyCreatedBean = this.currentlyCreatedBean.get();
if (currentlyCreatedBean != null) {
registerDependentBean(beanName, currentlyCreatedBean);
}
return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd);
}
AbstractBeanFactory:
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
//name所对应的bean实体是一个MapperFactoryBean对象,也就是一个FactoryBean对象。
//在条件判断中,最终会走到getObjectFromFactoryBean方法中
// 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.
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());
//通过父类的方法获取Bean实体
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
调用父类FactoryBeanRegistrySupport中的方法:
FactoryBeanRegistrySupport:
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
//mapper接口的代理还没有生成,这时获取的object为null
if (object == null) {
//执行doGetObjectFromFactoryBean方法
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)) {
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;
}
}
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
//没有获取到有效的SecurityManager,直接执行factory.getObject()方法
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
//这个factory实际上是MapperFactoryBean<com.interfaces.CityMapper>的实体对象
//接下来会执行MapperFactoryBean中的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;
}
开始通过MapperFactoryBean中的getObject方法获取相应的实体对象了:
@Override
public T getObject() throws Exception {
return getSqlSession().getMapper(this.mapperInterface);
}
这里会通过getSqlSession方法获取到SqlSessionTemplate对象,内部包含一个sqlSessionFactory对象。SqlSessionFactory的实现类为DefaultSqlSessionFactory。看一下SqlSessionTemplate中的getMapper方法:
@Override
public <T> T getMapper(Class<T> type) {
//调用内部的Configuration对象的getMapper方法
return getConfiguration().getMapper(type, this);
}
在Configuration对象中会直接调用MapperRegistry对象的getMapper方法,直接看一下MapperRegistry中的方法:
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
//这里的T其实就是在java中定义的mapper接口:com.interfaces.CityMapper
//在刚开始mapper接口注册的时候,根据接口类型创建了一个MapperProxyFactory实例
//并将实例保存在这个knownMappers集合中了,现在根据type重新取出保存的对象
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
//调用mapperProxyFactory的newInstance方法,创建一个MapperProxy实例
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
通过MapperProxyFactory中的newInstance方法创建一个MapperProxy实例对象并且返回给调用方也就是赋值给getBean的结果。
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
public T newInstance(SqlSession sqlSession) {
//新建一个MapperProxy对象,MapperProxy继承并实现了InvocationHandler接口
//其中mapperInterface是在java中定义的接口:com.interfaces.CityMapper
//methodCache是根据mapper配置文件解析方法
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
//通过MapperProxy生成一个T的动态代理对象
return newInstance(mapperProxy);
}
到此,关于Mybatis的整个加载流程和获取java中接口的动态代理对象的过程就到这里分析结束了,代码中都添加了注释,比较容易理解,就不多说了。
博客中难免会存在错误的地方,如果发现的话,麻烦给我留言帮助我修改错误!