View Javadoc
1   /*
2    *    Copyright 2009-2024 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.mybatis.guice;
17  
18  import static com.google.inject.name.Names.named;
19  import static com.google.inject.util.Providers.guicify;
20  import static org.mybatis.guice.Preconditions.checkArgument;
21  
22  import com.google.inject.Key;
23  import com.google.inject.Scopes;
24  import com.google.inject.TypeLiteral;
25  
26  import jakarta.inject.Provider;
27  
28  import java.util.Collection;
29  
30  import javax.sql.DataSource;
31  
32  import org.apache.ibatis.io.ResolverUtil;
33  import org.apache.ibatis.mapping.DatabaseIdProvider;
34  import org.apache.ibatis.mapping.Environment;
35  import org.apache.ibatis.plugin.Interceptor;
36  import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
37  import org.apache.ibatis.reflection.factory.ObjectFactory;
38  import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
39  import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
40  import org.apache.ibatis.scripting.LanguageDriver;
41  import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver;
42  import org.apache.ibatis.session.AutoMappingBehavior;
43  import org.apache.ibatis.session.Configuration;
44  import org.apache.ibatis.session.ExecutorType;
45  import org.apache.ibatis.session.LocalCacheScope;
46  import org.apache.ibatis.session.SqlSessionFactory;
47  import org.apache.ibatis.transaction.TransactionFactory;
48  import org.apache.ibatis.type.Alias;
49  import org.apache.ibatis.type.TypeHandler;
50  import org.mybatis.guice.binder.AliasBinder;
51  import org.mybatis.guice.binder.TypeHandlerBinder;
52  import org.mybatis.guice.configuration.ConfigurationProvider;
53  import org.mybatis.guice.configuration.ConfigurationSettingListener;
54  import org.mybatis.guice.configuration.settings.AggressiveLazyLoadingConfigurationSetting;
55  import org.mybatis.guice.configuration.settings.AliasConfigurationSetting;
56  import org.mybatis.guice.configuration.settings.AutoMappingBehaviorConfigurationSetting;
57  import org.mybatis.guice.configuration.settings.CacheEnabledConfigurationSetting;
58  import org.mybatis.guice.configuration.settings.ConfigurationSetting;
59  import org.mybatis.guice.configuration.settings.DefaultExecutorTypeConfigurationSetting;
60  import org.mybatis.guice.configuration.settings.DefaultScriptingLanguageTypeConfigurationSetting;
61  import org.mybatis.guice.configuration.settings.DefaultStatementTimeoutConfigurationSetting;
62  import org.mybatis.guice.configuration.settings.InterceptorConfigurationSettingProvider;
63  import org.mybatis.guice.configuration.settings.JavaTypeAndHandlerConfigurationSettingProvider;
64  import org.mybatis.guice.configuration.settings.LazyLoadingEnabledConfigurationSetting;
65  import org.mybatis.guice.configuration.settings.LocalCacheScopeConfigurationSetting;
66  import org.mybatis.guice.configuration.settings.MapUnderscoreToCamelCaseConfigurationSetting;
67  import org.mybatis.guice.configuration.settings.MapperConfigurationSetting;
68  import org.mybatis.guice.configuration.settings.MultipleResultSetsEnabledConfigurationSetting;
69  import org.mybatis.guice.configuration.settings.ObjectFactoryConfigurationSetting;
70  import org.mybatis.guice.configuration.settings.ObjectWrapperFactoryConfigurationSetting;
71  import org.mybatis.guice.configuration.settings.TypeHandlerConfigurationSettingProvider;
72  import org.mybatis.guice.configuration.settings.UseColumnLabelConfigurationSetting;
73  import org.mybatis.guice.configuration.settings.UseGeneratedKeysConfigurationSetting;
74  import org.mybatis.guice.environment.EnvironmentProvider;
75  import org.mybatis.guice.provision.ConfigurationProviderProvisionListener;
76  import org.mybatis.guice.provision.KeyMatcher;
77  import org.mybatis.guice.session.SqlSessionFactoryProvider;
78  import org.mybatis.guice.type.TypeHandlerProvider;
79  
80  /**
81   * Easy to use helper Module that alleviates users to write the boilerplate google-guice bindings to create the
82   * SqlSessionFactory.
83   */
84  public abstract class MyBatisModule extends AbstractMyBatisModule {
85  
86    /**
87     * The ObjectFactory class reference.
88     */
89    private Class<? extends ObjectFactory> objectFactoryType = DefaultObjectFactory.class;
90  
91    /**
92     * The ObjectWrapperFactory class reference.
93     */
94    private Class<? extends ObjectWrapperFactory> objectWrapperFactoryType = DefaultObjectWrapperFactory.class;
95    private Class<? extends LanguageDriver> defaultScriptingLanguageType = XMLLanguageDriver.class;
96  
97    /**
98     * The SqlSessionFactory Provider class reference.
99     */
100   private Class<? extends Provider<? extends SqlSessionFactory>> sqlSessionFactoryProviderType = SqlSessionFactoryProvider.class;
101 
102   private Class<? extends Provider<? extends Configuration>> configurationProviderType = ConfigurationProvider.class;
103 
104   @Override
105   final void internalConfigure() {
106     try {
107       initialize();
108 
109     } finally {
110 
111     }
112 
113     // fixed bindings
114     bind(Environment.class).toProvider(EnvironmentProvider.class).in(Scopes.SINGLETON);
115 
116     // replaceable bindings.
117     bind(Configuration.class).toProvider(configurationProviderType).in(Scopes.SINGLETON);
118     bind(SqlSessionFactory.class).toProvider(sqlSessionFactoryProviderType);
119 
120     // parametric bindings
121     bind(ObjectFactory.class).to(objectFactoryType).in(Scopes.SINGLETON);
122     bind(ObjectWrapperFactory.class).to(objectWrapperFactoryType).in(Scopes.SINGLETON);
123 
124     bindConfigurationSettingProvider(new ObjectFactoryConfigurationSetting(objectFactoryType));
125     bindConfigurationSettingProvider(new ObjectWrapperFactoryConfigurationSetting(objectWrapperFactoryType));
126     bindConfigurationSetting(new DefaultScriptingLanguageTypeConfigurationSetting(defaultScriptingLanguageType));
127   }
128 
129   /**
130    * Set the MyBatis configuration environment id.
131    *
132    * @param environmentId
133    *          the MyBatis configuration environment id
134    */
135   protected final void environmentId(String environmentId) {
136     checkArgument(environmentId != null, "Parameter 'environmentId' must be not null");
137     bindConstant().annotatedWith(named("mybatis.environment.id")).to(environmentId);
138   }
139 
140   /**
141    * Lazy loading enabled.
142    *
143    * @param lazyLoadingEnabled
144    *          the lazy loading enabled
145    */
146   protected final void lazyLoadingEnabled(boolean lazyLoadingEnabled) {
147     bindConfigurationSetting(new LazyLoadingEnabledConfigurationSetting(lazyLoadingEnabled));
148   }
149 
150   /**
151    * Aggressive lazy loading.
152    *
153    * @param aggressiveLazyLoading
154    *          the aggressive lazy loading
155    */
156   protected final void aggressiveLazyLoading(boolean aggressiveLazyLoading) {
157     bindConfigurationSetting(new AggressiveLazyLoadingConfigurationSetting(aggressiveLazyLoading));
158   }
159 
160   /**
161    * Multiple result sets enabled.
162    *
163    * @param multipleResultSetsEnabled
164    *          the multiple result sets enabled
165    */
166   protected final void multipleResultSetsEnabled(boolean multipleResultSetsEnabled) {
167     bindConfigurationSetting(new MultipleResultSetsEnabledConfigurationSetting(multipleResultSetsEnabled));
168   }
169 
170   /**
171    * Use generated keys.
172    *
173    * @param useGeneratedKeys
174    *          the use generated keys
175    */
176   protected final void useGeneratedKeys(boolean useGeneratedKeys) {
177     bindConfigurationSetting(new UseGeneratedKeysConfigurationSetting(useGeneratedKeys));
178   }
179 
180   /**
181    * Use column label.
182    *
183    * @param useColumnLabel
184    *          the use column label
185    */
186   protected final void useColumnLabel(boolean useColumnLabel) {
187     bindConfigurationSetting(new UseColumnLabelConfigurationSetting(useColumnLabel));
188   }
189 
190   /**
191    * Use cache enabled.
192    *
193    * @param useCacheEnabled
194    *          the use cache enabled
195    */
196   protected final void useCacheEnabled(boolean useCacheEnabled) {
197     bindConfigurationSetting(new CacheEnabledConfigurationSetting(useCacheEnabled));
198   }
199 
200   /**
201    * Use configuration provider.
202    *
203    * @param configurationProviderType
204    *          provider for Configuration
205    */
206   protected final void useConfigurationProvider(
207       Class<? extends Provider<? extends Configuration>> configurationProviderType) {
208     this.configurationProviderType = configurationProviderType;
209   }
210 
211   /**
212    * Use sql session factory provider.
213    *
214    * @param sqlSessionFactoryProvider
215    *          provider for SqlSessionFactory
216    */
217   protected final void useSqlSessionFactoryProvider(
218       Class<? extends Provider<? extends SqlSessionFactory>> sqlSessionFactoryProvider) {
219     this.sqlSessionFactoryProviderType = sqlSessionFactoryProvider;
220   }
221 
222   /**
223    * Fail fast.
224    *
225    * @param failFast
226    *          the fail fast
227    */
228   protected final void failFast(boolean failFast) {
229     bindBoolean("mybatis.configuration.failFast", failFast);
230   }
231 
232   /**
233    * Maps underscores to camel case.
234    *
235    * @param mapUnderscoreToCamelCase
236    *          Toggles this settings value.
237    */
238   protected final void mapUnderscoreToCamelCase(boolean mapUnderscoreToCamelCase) {
239     bindConfigurationSetting(new MapUnderscoreToCamelCaseConfigurationSetting(mapUnderscoreToCamelCase));
240   }
241 
242   /**
243    * set default statement timeout.
244    *
245    * @param defaultStatementTimeout
246    *          default statement timeout in seconds.
247    */
248   protected final void defaultStatementTimeout(Integer defaultStatementTimeout) {
249     bindConfigurationSetting(new DefaultStatementTimeoutConfigurationSetting(defaultStatementTimeout));
250   }
251 
252   protected final void bindConfigurationSetting(final ConfigurationSetting configurationSetting) {
253     bindListener(KeyMatcher.create(Key.get(ConfigurationSettingListener.class)),
254         ConfigurationProviderProvisionListener.create(configurationSetting));
255   }
256 
257   protected final <P extends Provider<? extends ConfigurationSetting>> void bindConfigurationSettingProvider(
258       P configurationSettingProvider) {
259     bindListener(KeyMatcher.create(Key.get(ConfigurationSettingListener.class)),
260         ConfigurationProviderProvisionListener.create(configurationSettingProvider, binder()));
261   }
262 
263   private final void bindBoolean(String name, boolean value) {
264     bindConstant().annotatedWith(named(name)).to(value);
265   }
266 
267   /**
268    * Executor type.
269    *
270    * @param executorType
271    *          the executor type
272    */
273   protected final void executorType(ExecutorType executorType) {
274     checkArgument(executorType != null, "Parameter 'executorType' must be not null");
275     bindConfigurationSetting(new DefaultExecutorTypeConfigurationSetting(executorType));
276   }
277 
278   /**
279    * Configures the local cache scope setting.
280    *
281    * @param localeCacheScope
282    *          The cache scope to use.
283    *
284    * @since 3.4
285    */
286   protected final void localCacheScope(LocalCacheScope localeCacheScope) {
287     checkArgument(localeCacheScope != null, "Parameter 'localCacheScope' must be not null");
288     bindConfigurationSetting(new LocalCacheScopeConfigurationSetting(localeCacheScope));
289   }
290 
291   /**
292    * Auto mapping behavior.
293    *
294    * @param autoMappingBehavior
295    *          the auto mapping behavior
296    */
297   protected final void autoMappingBehavior(AutoMappingBehavior autoMappingBehavior) {
298     checkArgument(autoMappingBehavior != null, "Parameter 'autoMappingBehavior' must be not null");
299     bindConfigurationSetting(new AutoMappingBehaviorConfigurationSetting(autoMappingBehavior));
300   }
301 
302   /**
303    * Set the DataSource Provider type has to be bound.
304    *
305    * @param dataSourceProviderType
306    *          the DataSource Provider type
307    */
308   protected final void bindDataSourceProviderType(Class<? extends Provider<DataSource>> dataSourceProviderType) {
309     checkArgument(dataSourceProviderType != null, "Parameter 'dataSourceProviderType' must be not null");
310     bind(DataSource.class).toProvider(dataSourceProviderType).in(Scopes.SINGLETON);
311   }
312 
313   /**
314    * Bind data source provider.
315    *
316    * @param dataSourceProvider
317    *          the data source provider
318    */
319   protected final void bindDataSourceProvider(Provider<DataSource> dataSourceProvider) {
320     checkArgument(dataSourceProvider != null, "Parameter 'dataSourceProvider' must be not null");
321     bindDataSourceProvider(guicify(dataSourceProvider));
322   }
323 
324   /**
325    * Bind data source provider.
326    *
327    * @param dataSourceProvider
328    *          the data source provider
329    */
330   protected final void bindDataSourceProvider(com.google.inject.Provider<DataSource> dataSourceProvider) {
331     checkArgument(dataSourceProvider != null, "Parameter 'dataSourceProvider' must be not null");
332     bind(DataSource.class).toProvider(dataSourceProvider).in(Scopes.SINGLETON);
333   }
334 
335   /**
336    * Bind database id provider.
337    *
338    * @param databaseIdProvider
339    *          The DatabaseIdProvider class.
340    */
341   protected final void bindDatabaseIdProvider(Class<? extends DatabaseIdProvider> databaseIdProvider) {
342     checkArgument(databaseIdProvider != null, "Parameter 'dataSourceProvider' must be not null");
343     bind(DatabaseIdProvider.class).to(databaseIdProvider).in(Scopes.SINGLETON);
344   }
345 
346   /**
347    * Bind database id provider.
348    *
349    * @param databaseIdProvider
350    *          The DatabaseIdProvider instance.
351    */
352   protected final void bindDatabaseIdProvider(DatabaseIdProvider databaseIdProvider) {
353     checkArgument(databaseIdProvider != null, "Parameter 'dataSourceProvider' must be not null");
354     bind(DatabaseIdProvider.class).toInstance(databaseIdProvider);
355   }
356 
357   /**
358    * Set the TransactionFactory type has to be bound.
359    *
360    * @param transactionFactoryType
361    *          the TransactionFactory type
362    */
363   protected final void bindTransactionFactoryType(Class<? extends TransactionFactory> transactionFactoryType) {
364     checkArgument(transactionFactoryType != null, "Parameter 'transactionFactoryType' must be not null");
365     bind(TransactionFactory.class).to(transactionFactoryType).in(Scopes.SINGLETON);
366   }
367 
368   /**
369    * Bind transaction factory.
370    *
371    * @param transactionFactoryProvider
372    *          the transaction factory provider
373    */
374   protected final void bindTransactionFactory(Provider<TransactionFactory> transactionFactoryProvider) {
375     checkArgument(transactionFactoryProvider != null, "Parameter 'transactionFactoryProvider' must be not null");
376     bindTransactionFactory(guicify(transactionFactoryProvider));
377   }
378 
379   /**
380    * Bind transaction factory.
381    *
382    * @param transactionFactoryProvider
383    *          the transaction factory provider
384    */
385   protected final void bindTransactionFactory(
386       com.google.inject.Provider<TransactionFactory> transactionFactoryProvider) {
387     checkArgument(transactionFactoryProvider != null, "Parameter 'transactionFactoryProvider' must be not null");
388     bind(TransactionFactory.class).toProvider(transactionFactoryProvider).in(Scopes.SINGLETON);
389   }
390 
391   /**
392    * Sets the ObjectFactory class.
393    *
394    * @param objectFactoryType
395    *          the ObjectFactory type
396    */
397   protected final void bindObjectFactoryType(Class<? extends ObjectFactory> objectFactoryType) {
398     checkArgument(objectFactoryType != null, "Parameter 'objectFactoryType' must be not null");
399     this.objectFactoryType = objectFactoryType;
400   }
401 
402   /**
403    * Sets the ObjectWrapperFactory class.
404    *
405    * @param objectWrapperFactoryType
406    *          the ObjectFactory type
407    */
408   protected final void bindObjectWrapperFactoryType(Class<? extends ObjectWrapperFactory> objectWrapperFactoryType) {
409     checkArgument(objectFactoryType != null, "Parameter 'objectWrapperFactoryType' must be not null");
410     this.objectWrapperFactoryType = objectWrapperFactoryType;
411   }
412 
413   /**
414    * Sets the default LanguageDriver class.
415    * <p>
416    * Due to current limitations in MyBatis, &#64;Inject cannot be used in LanguageDriver class.
417    * </p>
418    *
419    * @param defaultScriptingLanguageType
420    *          the default LanguageDriver type
421    */
422   protected final void bindDefaultScriptingLanguageType(Class<? extends LanguageDriver> defaultScriptingLanguageType) {
423     checkArgument(defaultScriptingLanguageType != null, "Parameter 'defaultScriptingLanguageType' must be not null");
424     this.defaultScriptingLanguageType = defaultScriptingLanguageType;
425   }
426 
427   /**
428    * Add a user defined binding.
429    *
430    * @param alias
431    *          the string type alias
432    *
433    * @return the alias binder
434    */
435   protected final AliasBinder addAlias(final String alias) {
436     checkArgument(alias != null && alias.length() > 0, "Empty or null 'alias' is not valid");
437 
438     return new AliasBinder() {
439 
440       @Override
441       public void to(final Class<?> clazz) {
442         checkArgument(clazz != null, "Null type not valid for alias '%s'", alias);
443         bindConfigurationSetting(new AliasConfigurationSetting(alias, clazz));
444       }
445 
446     };
447   }
448 
449   /**
450    * Adding simple aliases means that every specified class will be bound using the simple class name, i.e.
451    * {@code com.acme.Foo} becomes {@code Foo}.
452    *
453    * @param type
454    *          the specified types have to be bind
455    */
456   protected final void addSimpleAlias(final Class<?> type) {
457     checkArgument(type != null, "Parameter 'type' must be not null");
458 
459     String alias = type.getSimpleName();
460     // check if the class uses the Alias annotation.
461     final Alias annotation = type.getAnnotation(Alias.class);
462     if (annotation != null) {
463       alias = annotation.value();
464     }
465     addAlias(alias).to(type);
466   }
467 
468   /**
469    * Adding simple aliases means that every specified class will be bound using the simple class name, i.e.
470    * {@code com.acme.Foo} becomes {@code Foo}.
471    *
472    * @param types
473    *          the specified types have to be bind
474    */
475   protected final void addSimpleAliases(final Collection<Class<?>> types) {
476     checkArgument(types != null, "Parameter 'types' must be not null");
477 
478     for (Class<?> type : types) {
479       addSimpleAlias(type);
480     }
481   }
482 
483   /**
484    * Adds all Classes in the given package as a simple alias. Adding simple aliases means that every specified class
485    * will be bound using the simple class name, i.e. {@code com.acme.Foo} becomes {@code Foo}.
486    *
487    * @param packageName
488    *          the specified package to search for classes to alias.
489    * @param test
490    *          a test to run against the objects found in the specified package
491    */
492   protected final void addSimpleAliases(final String packageName, final ResolverUtil.Test test) {
493     addSimpleAliases(getClasses(test, packageName));
494   }
495 
496   /**
497    * Adds all Classes in the given package as a simple alias. Adding simple aliases means that every specified class
498    * will be bound using the simple class name, i.e. {@code com.acme.Foo} becomes {@code Foo}.
499    *
500    * @param packageName
501    *          the specified package to search for classes to alias
502    */
503   protected final void addSimpleAliases(final String packageName) {
504     addSimpleAliases(getClasses(packageName));
505   }
506 
507   /**
508    * Add a user defined Type Handler letting google-guice creating it.
509    *
510    * @param <T>
511    *          the generic type
512    * @param type
513    *          the specified type has to be handled.
514    *
515    * @return the type handler binder
516    */
517   protected final <T> TypeHandlerBinder<T> handleType(final Class<T> type) {
518     checkArgument(type != null, "Parameter 'type' must be not null");
519 
520     return new TypeHandlerBinder<T>() {
521 
522       @Override
523       public void with(final Class<? extends TypeHandler<? extends T>> handler) {
524         checkArgument(handler != null, "TypeHandler must not be null for '%s'", type.getName());
525 
526         bindTypeHandler(TypeLiteral.get(handler));
527         bindConfigurationSettingProvider(JavaTypeAndHandlerConfigurationSettingProvider.create(type, Key.get(handler)));
528       }
529 
530       @Override
531       public void with(final TypeLiteral<? extends TypeHandler<? extends T>> handler) {
532         checkArgument(handler != null, "TypeHandler must not be null for '%s'", type.getName());
533 
534         bindTypeHandler(handler);
535         bindConfigurationSettingProvider(JavaTypeAndHandlerConfigurationSettingProvider.create(type, Key.get(handler)));
536       }
537 
538       @Override
539       public void withProvidedTypeHandler(final Class<? extends TypeHandler<? extends T>> handler) {
540         checkArgument(handler != null, "TypeHandler must not be null for '%s'", type.getName());
541 
542         bindProvidedTypeHandler(TypeLiteral.get(handler), type);
543         bindConfigurationSettingProvider(JavaTypeAndHandlerConfigurationSettingProvider.create(type, Key.get(handler)));
544       }
545 
546       @Override
547       public void withProvidedTypeHandler(final TypeLiteral<? extends TypeHandler<? extends T>> handler) {
548         checkArgument(handler != null, "TypeHandler must not be null for '%s'", type.getName());
549 
550         bindProvidedTypeHandler(handler, type);
551         bindConfigurationSettingProvider(JavaTypeAndHandlerConfigurationSettingProvider.create(type, Key.get(handler)));
552       }
553 
554       final <TH extends TypeHandler<? extends T>> void bindTypeHandler(TypeLiteral<TH> typeHandlerType) {
555         bind(typeHandlerType).in(Scopes.SINGLETON);
556       }
557 
558       final <TH extends TypeHandler<? extends T>> void bindProvidedTypeHandler(TypeLiteral<TH> typeHandlerType,
559           Class<T> type) {
560         bind(typeHandlerType).toProvider(guicify(new TypeHandlerProvider<TH, T>(typeHandlerType, type)))
561             .in(Scopes.SINGLETON);
562       }
563     };
564   }
565 
566   /**
567    * Adds the user defined MyBatis type handler, letting google-guice creating it.
568    *
569    * @param handlerClass
570    *          the handler type.
571    */
572   protected final void addTypeHandlerClass(final Class<? extends TypeHandler<?>> handlerClass) {
573     checkArgument(handlerClass != null, "Parameter 'handlerClass' must not be null");
574     bind(TypeLiteral.get(handlerClass)).in(Scopes.SINGLETON);
575 
576     bindConfigurationSettingProvider(new TypeHandlerConfigurationSettingProvider(Key.get(handlerClass)));
577   }
578 
579   /**
580    * Adds the user defined MyBatis type handlers, letting google-guice creating it.
581    *
582    * @param handlersClasses
583    *          the handler type.
584    */
585   protected final void addTypeHandlersClasses(Collection<Class<? extends TypeHandler<?>>> handlersClasses) {
586     checkArgument(handlersClasses != null, "Parameter 'handlersClasses' must not be null");
587 
588     for (Class<? extends TypeHandler<?>> handlerClass : handlersClasses) {
589       addTypeHandlerClass(handlerClass);
590     }
591   }
592 
593   /**
594    * Adds the user defined MyBatis type handlers in the given package, letting google-guice creating it.
595    *
596    * @param packageName
597    *          the package where looking for type handlers.
598    */
599   protected final void addTypeHandlerClasses(String packageName) {
600     checkArgument(packageName != null, "Parameter 'packageName' must not be null");
601     addTypeHandlersClasses(
602         new ResolverUtil<TypeHandler<?>>().find(new ResolverUtil.IsA(TypeHandler.class), packageName).getClasses());
603   }
604 
605   /**
606    * Adds the user defined myBatis interceptor plugins type, letting google-guice creating it.
607    *
608    * @param interceptorClass
609    *          The user defined MyBatis interceptor plugin type
610    */
611   protected final void addInterceptorClass(final Class<? extends Interceptor> interceptorClass) {
612     checkArgument(interceptorClass != null, "Parameter 'interceptorClass' must not be null");
613     bindConfigurationSettingProvider(new InterceptorConfigurationSettingProvider(interceptorClass));
614   }
615 
616   /**
617    * Adds the user defined MyBatis interceptors plugins types, letting google-guice creating them.
618    *
619    * @param interceptorsClasses
620    *          the user defined MyBatis Interceptors plugins types
621    */
622   protected final void addInterceptorsClasses(Collection<Class<? extends Interceptor>> interceptorsClasses) {
623     checkArgument(interceptorsClasses != null, "Parameter 'interceptorsClasses' must not be null");
624 
625     for (Class<? extends Interceptor> interceptorClass : interceptorsClasses) {
626       addInterceptorClass(interceptorClass);
627     }
628   }
629 
630   /**
631    * Adds the user defined MyBatis interceptors plugins types in the given package, letting google-guice creating them.
632    *
633    * @param packageName
634    *          the package where looking for Interceptors plugins types.
635    */
636   protected final void addInterceptorsClasses(String packageName) {
637     checkArgument(packageName != null, "Parameter 'packageName' must not be null");
638     addInterceptorsClasses(
639         new ResolverUtil<Interceptor>().find(new ResolverUtil.IsA(Interceptor.class), packageName).getClasses());
640   }
641 
642   /**
643    * Adds the user defined mapper classes.
644    *
645    * @param mapperClass
646    *          the user defined mapper classes.
647    */
648   protected final void addMapperClass(Class<?> mapperClass) {
649     checkArgument(mapperClass != null, "Parameter 'mapperClass' must not be null");
650 
651     bindListener(KeyMatcher.create(Key.get(ConfigurationSettingListener.class)),
652         ConfigurationProviderProvisionListener.create(new MapperConfigurationSetting(mapperClass)));
653     bindMapper(mapperClass);
654   }
655 
656   /**
657    * Adds the user defined mapper classes.
658    *
659    * @param mapperClasses
660    *          the user defined mapper classes
661    */
662   protected final void addMapperClasses(Collection<Class<?>> mapperClasses) {
663     checkArgument(mapperClasses != null, "Parameter 'mapperClasses' must not be null");
664 
665     for (Class<?> mapperClass : mapperClasses) {
666       addMapperClass(mapperClass);
667     }
668   }
669 
670   /**
671    * Adds the user defined mapper classes.
672    *
673    * @param packageName
674    *          the specified package to search for mappers to add.
675    */
676   protected final void addMapperClasses(final String packageName) {
677     addMapperClasses(getClasses(packageName));
678   }
679 
680   /**
681    * Adds the user defined mapper classes.
682    *
683    * @param packageName
684    *          the specified package to search for mappers to add.
685    * @param test
686    *          a test to run against the objects found in the specified package.
687    */
688   protected final void addMapperClasses(final String packageName, final ResolverUtil.Test test) {
689     addMapperClasses(getClasses(test, packageName));
690   }
691 }