Mybatis整合Spring之MapperFactoryBean简单分析

MapperFactoryBean分析:

MapperFactoryBean的运作原理到底是什么?

继承关系如下图所示:

Mybatis整合Spring之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动态代理的模式

上一篇:MyFreeMarkerConfigurer


下一篇:python 生成训练数据的txt文件