MapperFactoryBean分析:
MapperFactoryBean的运作原理到底是什么?
继承关系如下图所示:
分析:
1.FactoryBean可以整合到Spring中,其中内部 getObject() 就是实际注册到容器中的对象,getObjectType()就是注册到容器中的类型
2.另外层层集成直到实现InitializingBean,内部具有 afterPropertiesSet() 也是Spring组件在创建的,设置好相关的属性之后就会调用这个方法。
其中 afterPropertiesSet() 在Spring的执行时机
// 前方调用
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
// 后方调用
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
其中DaoSupport重写了
public final void afterPropertiesSet() throws IllegalArgumentException, BeanInitializationException {
this.checkDaoConfig();
try {
this.initDao();
} catch (Exception var2) {
throw new BeanInitializationException("Initialization of DAO failed", var2);
}
}
发现内部调用了 checkDaoConfig() 与 initDao()方法
其中 checkDaoConfig() 被SqlSessionDaoSupport重写,但是又被其父类MapperFactoryBean重写了如下:
protected void checkDaoConfig() {
super.checkDaoConfig();
Assert.notNull(this.mapperInterface, "Property 'mapperInterface' is required");
Configuration configuration = this.getSqlSession().getConfiguration();
if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) {
try {
configuration.addMapper(this.mapperInterface);
} catch (Exception var6) {
this.logger.error("Error while adding the mapper '" + this.mapperInterface + "' to configuration.", var6);
throw new IllegalArgumentException(var6);
} finally {
ErrorContext.instance().reset();
}
}
}
其中 initDao() 没有被父类重写,且自己这是个空方法,什么也不做
其中 getObject() 干了什么?
public T getObject() throws Exception {
return this.getSqlSession().getMapper(this.mapperInterface);
}
其中mapperInterface就是我们bean组件显示赋值我们mapper的接口的全路径,是Class
点进 getMapper(this.mapperInterface)方法,里面任何一个实现类大致的写法都是如下
return this.configuration.getMapper(type, this);
点进 getMapper(type, this)方法
return this.mapperRegistry.getMapper(type, sqlSession);
点进 getMapper(type, sqlSession)方法
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);
}
}
}
看到了,将sqlSession传进去准备构建代理对象
protected T newInstance(MapperProxy<T> mapperProxy) {
return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);
}
public T newInstance(SqlSession sqlSession) {
MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache);
return this.newInstance(mapperProxy);
}
显然用的是Jdk动态代理的模式