还是AOP: MyBatis mapper的实现

2020-06-08  本文已影响0人  overflowedstack
写在前面 - 回顾一下MyBatis中的配置

db entity:

public class TestUser {
    private String userName;
    private LocalDateTime createDt;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public LocalDateTime getCreateDt() {
        return createDt;
    }

    public void setCreateDt(LocalDateTime createDt) {
        this.createDt = createDt;
    }
}

mapper接口:

public interface TestUserMapper {
    public TestUser getTestUserById(Long id);
}

mapper xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="server.db.entity.TestUserMapper">
    <select id="getTestUserById" resultType="testUser" parameterType="Long">
        SELECT top 1 * from TEST_USER where id = #{id}
    </select>
</mapper>

db-config.xml

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="myDataSource"/>
        <property name="configLocation" value="mybatis-config.xml"/>
    </bean>
    
    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" />
    </bean>
    
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="server.db.entity" /> 
        <property name="sqlSessionTemplateBeanName" value="sqlSessionTemplate" />
    </bean>

使用:

        TestUserMapper userMapper = (TestUserMapper)context.getBean(TestUserMapper.class);
        TestUser user = userMapper.getTestUserById(Long.valueOf(1));
        System.out.println(user);

问题来了,仅仅定义了mapper接口,并没有实现类,怎么就能调用它的方法了呢?
这是因为在运行时采用动态代理技术生成了代理类,调用的是代理类的实现方法。来看一下这个代理类是怎样生成的。

1. 创建mapper代理类

Spring容器初始化testUserMapper,发现它的root bean是MapperFactoryBean,这是一个工厂bean。

public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T>

当后面getMapper时,spring容器查到这是一个工厂bean,就会调用MapperFactoryBean的如下getObject方法来创建真正的bean。

  @Override
  public T getObject() throws Exception {
    return getSqlSession().getMapper(this.mapperInterface);
  }

里面会采用动态代理来生成相应的代理类。

  @SuppressWarnings("unchecked")
  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    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);
    }
  }

MapperProxyFactory:

  @SuppressWarnings("unchecked")
  protected T newInstance(MapperProxy<T> mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

  public T newInstance(SqlSession sqlSession) {
    final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy);
  }
2. 生成的mapper代理类
public final class $Proxy44 extends Proxy implements TestUserMapper {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public $Proxy44(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final TestUser getTestUserById(Long var1) throws  {
        try {
            return (TestUser)super.h.invoke(this, m3, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("com.server.autoVerification.db.entity.TestUserMapper").getMethod("getTestUserById", Class.forName("java.lang.Long"));
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}



上一篇 下一篇

猜你喜欢

热点阅读