您现在的位置是:主页 > news > 找哪里做网站/百度指数搜索

找哪里做网站/百度指数搜索

admin2025/5/5 14:14:21news

简介找哪里做网站,百度指数搜索,河北专业网站制作,石家庄模板建站系统知识储备 SqlsessionFactory-mybatis持久层操作数据的前提,具体的解析是通过SqlSessionFactoryBean生成的,可见>>>Spring mybatis源码篇章-SqlSessionFactoryBeanMapperInterface-mybatis的java接口类,用于service/controller层的调…

找哪里做网站,百度指数搜索,河北专业网站制作,石家庄模板建站系统知识储备 SqlsessionFactory-mybatis持久层操作数据的前提,具体的解析是通过SqlSessionFactoryBean生成的,可见>>>Spring mybatis源码篇章-SqlSessionFactoryBeanMapperInterface-mybatis的java接口类,用于service/controller层的调…

知识储备

  1. SqlsessionFactory-mybatis持久层操作数据的前提,具体的解析是通过SqlSessionFactoryBean生成的,可见>>>Spring mybatis源码篇章-SqlSessionFactoryBean

  2. MapperInterface-mybatis的java接口类,用于service/controller层的调用,具体的解析可见>>>Spring mybatis源码篇章-MapperScannerConfigurer关联dao接口

  3. 保存mybatis的各种信息都是由org.apache.ibatis.session.Configuration类来维护的

入口

入口由Configuration#addMapper()方法调用,如下述MapperFactoryBean#checkConfig()源码

  @Overrideprotected void checkDaoConfig() {super.checkDaoConfig();notNull(this.mapperInterface, "Property 'mapperInterface' is required");Configuration configuration = getSqlSession().getConfiguration();if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) {try {//只关注此处的添加mapper接口configuration.addMapper(this.mapperInterface);} catch (Throwable t) {throw new IllegalArgumentException(t);} finally {ErrorContext.instance().reset();}}}

具体的调用哪个类进行代理的生成,我们继续往下查看

MapperRegistry#addMapper()

通过MapperRegistry来创建mapper访问代理,直接阅读源码

  public <T> void addMapper(Class<T> type) {if (type.isInterface()) {if (hasMapper(type)) {throw new BindingException("Type " + type + " is already known to the MapperRegistry.");}boolean loadCompleted = false;try {//将mapper接口包装成mapper代理knownMappers.put(type, new MapperProxyFactory<T>(type));//解析接口上的注解或者加载mapper配置文件生成mappedStatementMapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);parser.parse();loadCompleted = true;} finally {if (!loadCompleted) {knownMappers.remove(type);}}}}

此处笔者只关注MapperProxyFactory类,其是生成mapper代理的关键

MapperProxyFactory

  • 内部属性概览
  //被代理类private final Class<T> mapperInterface;//支持对被代理类进行缓存private Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<Method, MapperMethod>();
  • 创建代理类
      @SuppressWarnings("unchecked")protected T newInstance(MapperProxy<T> mapperProxy) {//采用JDK自带的Proxy代理模式生成return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);}public T newInstance(SqlSession sqlSession) {//MapperProxy为InvocationHandler的实现类final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);//真实生成代理return newInstance(mapperProxy);}

接下来阅读下MapperProxy是怎么运用反射调用mapper接口类的方法

MapperProxy

由于要使用JDK的动态代理,直接InvokeHandler接口的实现方法

      @Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (Object.class.equals(method.getDeclaringClass())) {try {return method.invoke(this, args);} catch (Throwable t) {throw ExceptionUtil.unwrapThrowable(t);}}//尝试从缓存中获取,也就是看到的methodCachefinal MapperMethod mapperMethod = cachedMapperMethod(method);//通过MapperMethod对象调用方法return mapperMethod.execute(sqlSession, args);}private MapperMethod cachedMapperMethod(Method method) {MapperMethod mapperMethod = methodCache.get(method);if (mapperMethod == null) {//注意此处的传的参数为mapper接口类、method对象、Configuration对象mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());methodCache.put(method, mapperMethod);}return mapperMethod;}

由上文我们找到了代理的关键处理类MapperMethod,笔者继续往下一窥究竟

MapperMethod

  • 构造函数
      //Sql指令类private final SqlCommand command;//方法签名类private final MethodSignature method;public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {this.command = new SqlCommand(config, mapperInterface, method);this.method = new MethodSignature(config, method);}
  • 代理dao接口对应出口方法execute()
  public Object execute(SqlSession sqlSession, Object[] args) {Object result;//CURD操作,对持久层返回的结果集进行处理if (SqlCommandType.INSERT == command.getType()) {//获取method方法上的带有@Param的参数,默认返回0,1,2,3...Object param = method.convertArgsToSqlCommandParam(args);//最终是通过sqlSession接口对象获取结果集,注意此处的command.getName()为mappedStatementIdresult = rowCountResult(sqlSession.insert(command.getName(), param));} else if (SqlCommandType.UPDATE == command.getType()) {Object param = method.convertArgsToSqlCommandParam(args);result = rowCountResult(sqlSession.update(command.getName(), param));} else if (SqlCommandType.DELETE == command.getType()) {Object param = method.convertArgsToSqlCommandParam(args);result = rowCountResult(sqlSession.delete(command.getName(), param));} else if (SqlCommandType.SELECT == command.getType()) {//查询语句的各种情况应对if (method.returnsVoid() && method.hasResultHandler()) {executeWithResultHandler(sqlSession, args);result = null;} else if (method.returnsMany()) {result = executeForMany(sqlSession, args);} else if (method.returnsMap()) {result = executeForMap(sqlSession, args);} else {Object param = method.convertArgsToSqlCommandParam(args);result = sqlSession.selectOne(command.getName(), param);}} else {throw new BindingException("Unknown execution method for: " + command.getName());}return result;}
  1. SqlCommand是MapperMethod的静态内部类,主要通过mapperInterface和method从Configuration中获取MappedStatement对象保存其id和type属性,供sqlsession持久层接口调用

  2. MethodSignature是MappedMethod的静态内部类,主要对代理的method作下反射处理,包括入参、出参等操作

  3. MapperMethod的作用是处理SqlSession接口调用CRUD操作后产生的结果集

MapperRegistry#getMapper()

相对应的获取mapper代理类,源码如下

  @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 {//获取mapper代理类return mapperProxyFactory.newInstance(sqlSession);} catch (Exception e) {throw new BindingException("Error getting mapper instance. Cause: " + e, e);}}

那么获取代理类这个操作是如何被调用的呢?这其实是bean工厂对其里面所有的beanDefinition进行实例化调用的,这点可查看>>>Spring源码情操陶冶-AbstractApplicationContext#finishBeanFactoryInitialization。
而针对FactoryBean接口的实例化会调用其中的getObject()方法,所以我们看下MapperFactoryBean#getObject()方法

  public T getObject() throws Exception {//通过sqlSessionTemplate调用Configuration#getMapper()方法间接调用MapperRegistry#getMapper()return getSqlSession().getMapper(this.mapperInterface);}

小结

本文是对MapperFactoryBean#checkDaoConfig()方法的补充,通过对Mybatis的MapperRegistry的分析我们可以得出以下结论:

  • mapperInterface的内部方法数据持久层访问是通过JDK的代理来完成的

  • MapperMethod是对上述代理的method方法的真实处理,主要是对sqlSession的返回结果集进行对应的整理输出,具体读者可自行查阅分析

转载于:https://www.cnblogs.com/question-sky/p/7251399.html