MapperRegistry.java

  1. /*
  2.  *    Copyright 2009-2023 the original author or authors.
  3.  *
  4.  *    Licensed under the Apache License, Version 2.0 (the "License");
  5.  *    you may not use this file except in compliance with the License.
  6.  *    You may obtain a copy of the License at
  7.  *
  8.  *       https://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  *    Unless required by applicable law or agreed to in writing, software
  11.  *    distributed under the License is distributed on an "AS IS" BASIS,
  12.  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  *    See the License for the specific language governing permissions and
  14.  *    limitations under the License.
  15.  */
  16. package org.apache.ibatis.binding;

  17. import java.util.Collection;
  18. import java.util.Collections;
  19. import java.util.Map;
  20. import java.util.Set;
  21. import java.util.concurrent.ConcurrentHashMap;

  22. import org.apache.ibatis.builder.annotation.MapperAnnotationBuilder;
  23. import org.apache.ibatis.io.ResolverUtil;
  24. import org.apache.ibatis.session.Configuration;
  25. import org.apache.ibatis.session.SqlSession;

  26. /**
  27.  * @author Clinton Begin
  28.  * @author Eduardo Macarron
  29.  * @author Lasse Voss
  30.  */
  31. public class MapperRegistry {

  32.   private final Configuration config;
  33.   private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new ConcurrentHashMap<>();

  34.   public MapperRegistry(Configuration config) {
  35.     this.config = config;
  36.   }

  37.   @SuppressWarnings("unchecked")
  38.   public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
  39.     final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
  40.     if (mapperProxyFactory == null) {
  41.       throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
  42.     }
  43.     try {
  44.       return mapperProxyFactory.newInstance(sqlSession);
  45.     } catch (Exception e) {
  46.       throw new BindingException("Error getting mapper instance. Cause: " + e, e);
  47.     }
  48.   }

  49.   public <T> boolean hasMapper(Class<T> type) {
  50.     return knownMappers.containsKey(type);
  51.   }

  52.   public <T> void addMapper(Class<T> type) {
  53.     if (type.isInterface()) {
  54.       if (hasMapper(type)) {
  55.         throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
  56.       }
  57.       boolean loadCompleted = false;
  58.       try {
  59.         knownMappers.put(type, new MapperProxyFactory<>(type));
  60.         // It's important that the type is added before the parser is run
  61.         // otherwise the binding may automatically be attempted by the
  62.         // mapper parser. If the type is already known, it won't try.
  63.         MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
  64.         parser.parse();
  65.         loadCompleted = true;
  66.       } finally {
  67.         if (!loadCompleted) {
  68.           knownMappers.remove(type);
  69.         }
  70.       }
  71.     }
  72.   }

  73.   /**
  74.    * Gets the mappers.
  75.    *
  76.    * @return the mappers
  77.    *
  78.    * @since 3.2.2
  79.    */
  80.   public Collection<Class<?>> getMappers() {
  81.     return Collections.unmodifiableCollection(knownMappers.keySet());
  82.   }

  83.   /**
  84.    * Adds the mappers.
  85.    *
  86.    * @param packageName
  87.    *          the package name
  88.    * @param superType
  89.    *          the super type
  90.    *
  91.    * @since 3.2.2
  92.    */
  93.   public void addMappers(String packageName, Class<?> superType) {
  94.     ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<>();
  95.     resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
  96.     Set<Class<? extends Class<?>>> mapperSet = resolverUtil.getClasses();
  97.     for (Class<?> mapperClass : mapperSet) {
  98.       addMapper(mapperClass);
  99.     }
  100.   }

  101.   /**
  102.    * Adds the mappers.
  103.    *
  104.    * @param packageName
  105.    *          the package name
  106.    *
  107.    * @since 3.2.2
  108.    */
  109.   public void addMappers(String packageName) {
  110.     addMappers(packageName, Object.class);
  111.   }

  112. }