Skip to content

Commit 7da2d39

Browse files
authored
Merge pull request #438 from tacoo/mapperscan
Use declared class's package as base package if not present base packages on @MapperScan
2 parents 7811be4 + a9fce71 commit 7da2d39

File tree

11 files changed

+115
-7
lines changed

11 files changed

+115
-7
lines changed

src/main/java/org/mybatis/spring/annotation/MapperScan.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@
3131
/**
3232
* Use this annotation to register MyBatis mapper interfaces when using Java Config. It performs when same work as
3333
* {@link MapperScannerConfigurer} via {@link MapperScannerRegistrar}.
34+
*
35+
* <p>Either {@link #basePackageClasses} or {@link #basePackages} (or its alias
36+
* {@link #value}) may be specified to define specific packages to scan.
37+
* Since 2.0.4, If specific packages are not defined, scanning will occur from
38+
* the package of the class that declares this annotation.
3439
*
3540
* <p>
3641
* Configuration example:

src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, B
7070
AnnotationAttributes mapperScanAttrs = AnnotationAttributes
7171
.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
7272
if (mapperScanAttrs != null) {
73-
registerBeanDefinitions(mapperScanAttrs, registry, generateBaseBeanName(importingClassMetadata, 0));
73+
registerBeanDefinitions(importingClassMetadata, mapperScanAttrs, registry, generateBaseBeanName(importingClassMetadata, 0));
7474
}
7575
}
7676

77-
void registerBeanDefinitions(AnnotationAttributes annoAttrs, BeanDefinitionRegistry registry, String beanName) {
77+
void registerBeanDefinitions(AnnotationMetadata annoMeta, AnnotationAttributes annoAttrs, BeanDefinitionRegistry registry, String beanName) {
7878

7979
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);
8080
builder.addPropertyValue("processPropertyPlaceHolders", true);
@@ -119,6 +119,10 @@ void registerBeanDefinitions(AnnotationAttributes annoAttrs, BeanDefinitionRegis
119119
basePackages.addAll(Arrays.stream(annoAttrs.getClassArray("basePackageClasses")).map(ClassUtils::getPackageName)
120120
.collect(Collectors.toList()));
121121

122+
if (basePackages.isEmpty()) {
123+
basePackages.add(getDefaultBasePackage(annoMeta));
124+
}
125+
122126
String lazyInitialization = annoAttrs.getString("lazyInitialization");
123127
if (StringUtils.hasText(lazyInitialization)) {
124128
builder.addPropertyValue("lazyInitialization", lazyInitialization);
@@ -134,6 +138,10 @@ private static String generateBaseBeanName(AnnotationMetadata importingClassMeta
134138
return importingClassMetadata.getClassName() + "#" + MapperScannerRegistrar.class.getSimpleName() + "#" + index;
135139
}
136140

141+
private static String getDefaultBasePackage(AnnotationMetadata importingClassMetadata) {
142+
return ClassUtils.getPackageName(importingClassMetadata.getClassName());
143+
}
144+
137145
/**
138146
* A {@link MapperScannerRegistrar} for {@link MapperScans}.
139147
*
@@ -150,7 +158,7 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, B
150158
if (mapperScansAttrs != null) {
151159
AnnotationAttributes[] annotations = mapperScansAttrs.getAnnotationArray("value");
152160
for (int i = 0; i < annotations.length; i++) {
153-
registerBeanDefinitions(annotations[i], registry, generateBaseBeanName(importingClassMetadata, i));
161+
registerBeanDefinitions(importingClassMetadata, annotations[i], registry, generateBaseBeanName(importingClassMetadata, i));
154162
}
155163
}
156164
}

src/site/es/xdoc/mappers.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,11 @@ public class AppConfig {
234234
Tambien puedes indicar una <code>SqlSessionFactory</code> o un <code>SqlSessionTemplate</code> específicos
235235
mediante las propiedades <code>sqlSessionFactory</code> y <code>sqlSessionTemplate</code>.
236236
</p>
237-
237+
238+
<p>
239+
<span class="label important">NOTE</span> Since 2.0.4, If <code>basePackageClasses</code> or <code>basePackages</code> are not defined, scanning will occur from the package of the class that declares this annotation.
240+
</p>
241+
238242
<h4>MapperScannerConfigurer</h4>
239243

240244
<p>

src/site/ja/xdoc/mappers.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,11 @@ public class AppConfig {
210210
このアノテーションは前章で説明した <code>&lt;mybatis:scan/&gt;</code> と全く同じ要領で Mapper の検出を行います。
211211
引数 <code>markerInterface</code>, <code>annotationClass</code> を使えば検出対象のマーカーインターフェイスとアノテーションを指定することもできますし、<code>sqlSessionFactory</code>, <code>sqlSessionTemplate</code> で <code>SqlSessionFactory</code> や <code>SqlSessionTemplate</code> を指定することができます。
212212
</p>
213-
213+
214+
<p>
215+
<span class="label important">NOTE</span> 2.0.4以降では、 <code>basePackageClasses</code> もしくは <code>basePackages</code> が指定されていない場合、このアノテーションが定義されているクラスのパッケージを基準にスキャンします。
216+
</p>
217+
214218
<h4>MapperScannerConfigurer</h4>
215219

216220
<p>

src/site/ko/xdoc/mappers.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,11 @@ public class AppConfig {
191191
<code>markerInterface</code> 와 <code>annotationClass</code> 프로퍼티를 사용해서 마커 인터페이스와 애노테이션 클래스를 명시하게 한다.
192192
<code>sqlSessionFactory</code> 와 <code>sqlSessionTemplate</code> 프로퍼티를 사용해서
193193
<code>SqlSessionFactory</code> 나 <code>SqlSessionTemplate</code>을 제공할 수도 있다. </p>
194-
194+
195+
<p>
196+
<span class="label important">NOTE</span> Since 2.0.4, If <code>basePackageClasses</code> or <code>basePackages</code> are not defined, scanning will occur from the package of the class that declares this annotation.
197+
</p>
198+
195199
<h4>MapperScannerConfigurer</h4>
196200

197201
<p><code>MapperScannerConfigurer</code>는 평범한 빈처럼 XML애플리케이션 컨텍스트에 포함된 <code>BeanDefinitionRegistryPostProcessor</code> 이다.

src/site/xdoc/mappers.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,11 @@ public class AppConfig {
247247
You can also provide an specific <code>SqlSessionFactory</code> or <code>SqlSessionTemplate</code>
248248
by using its properties <code>sqlSessionFactory</code> and <code>sqlSessionTemplate</code>.
249249
</p>
250-
250+
251+
<p>
252+
<span class="label important">NOTE</span> Since 2.0.4, If <code>basePackageClasses</code> or <code>basePackages</code> are not defined, scanning will occur from the package of the class that declares this annotation.
253+
</p>
254+
251255
<h4>MapperScannerConfigurer</h4>
252256

253257
<p>

src/site/zh/xdoc/mappers.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,10 @@ public class AppConfig {
195195
这个注解具有与之前见过的 <code>&lt;mybatis:scan/&gt;</code> 元素一样的工作方式。它也可以通过 <code>markerInterface</code> 和 <code>annotationClass</code> 属性设置标记接口或注解类。通过配置 <code>sqlSessionFactory</code> 和 <code>sqlSessionTemplate</code> 属性,你还能指定一个 <code>SqlSessionFactory</code> 或 <code>SqlSessionTemplate</code>。
196196
</p>
197197

198+
<p>
199+
<span class="label important">NOTE</span> Since 2.0.4, If <code>basePackageClasses</code> or <code>basePackages</code> are not defined, scanning will occur from the package of the class that declares this annotation.
200+
</p>
201+
198202
<h4>MapperScannerConfigurer</h4>
199203

200204
<p>

src/test/java/org/mybatis/spring/annotation/MapperScanTest.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@
2626
import org.junit.jupiter.api.Test;
2727
import org.mybatis.spring.SqlSessionFactoryBean;
2828
import org.mybatis.spring.SqlSessionTemplate;
29+
import org.mybatis.spring.annotation.mapper.ds1.AppConfigWithDefaultMapperScanAndRepeat;
30+
import org.mybatis.spring.annotation.mapper.ds1.AppConfigWithDefaultMapperScans;
2931
import org.mybatis.spring.annotation.mapper.ds1.Ds1Mapper;
3032
import org.mybatis.spring.mapper.AnnotatedMapper;
33+
import org.mybatis.spring.mapper.AppConfigWithDefaultPackageScan;
3134
import org.mybatis.spring.mapper.MapperInterface;
3235
import org.mybatis.spring.mapper.MapperSubinterface;
3336
import org.mybatis.spring.mapper.child.MapperChildInterface;
@@ -90,6 +93,19 @@ void assertNoMapperClass() {
9093
}
9194
}
9295

96+
@Test
97+
void testDefaultMapperScan() {
98+
applicationContext.register(AppConfigWithDefaultPackageScan.class);
99+
100+
startContext();
101+
102+
// all interfaces with methods should be loaded
103+
applicationContext.getBean("mapperInterface");
104+
applicationContext.getBean("mapperSubinterface");
105+
applicationContext.getBean("mapperChildInterface");
106+
applicationContext.getBean("annotatedMapper");
107+
}
108+
93109
@Test
94110
void testInterfaceScan() {
95111
applicationContext.register(AppConfigWithPackageScan.class);
@@ -275,6 +291,32 @@ void testScanWithMapperScans() {
275291
applicationContext.getBean("ds2Mapper");
276292
}
277293

294+
@Test
295+
void testScanWithDefaultMapperScanAndRepeat() {
296+
applicationContext.register(AppConfigWithDefaultMapperScanAndRepeat.class);
297+
298+
startContext();
299+
300+
SqlSessionFactory sqlSessionFactory = applicationContext.getBean(SqlSessionFactory.class);
301+
assertEquals(2, sqlSessionFactory.getConfiguration().getMapperRegistry().getMappers().size());
302+
303+
applicationContext.getBean("ds1Mapper");
304+
applicationContext.getBean("ds2Mapper");
305+
}
306+
307+
@Test
308+
void testScanWithDefaultMapperScans() {
309+
applicationContext.register(AppConfigWithDefaultMapperScans.class);
310+
311+
startContext();
312+
313+
SqlSessionFactory sqlSessionFactory = applicationContext.getBean(SqlSessionFactory.class);
314+
assertEquals(2, sqlSessionFactory.getConfiguration().getMapperRegistry().getMappers().size());
315+
316+
applicationContext.getBean("ds1Mapper");
317+
applicationContext.getBean("ds2Mapper");
318+
}
319+
278320
@Test
279321
void testLazyScanWithPropertySourcesPlaceholderConfigurer() {
280322
applicationContext.register(LazyConfigWithPropertySourcesPlaceholderConfigurer.class);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.mybatis.spring.annotation.mapper.ds1;
2+
3+
import org.mybatis.spring.annotation.MapperScan;
4+
import org.springframework.context.annotation.Configuration;
5+
6+
@Configuration
7+
@MapperScan
8+
@MapperScan("org.mybatis.spring.annotation.mapper.ds2")
9+
public class AppConfigWithDefaultMapperScanAndRepeat {
10+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.mybatis.spring.annotation.mapper.ds1;
2+
3+
import org.mybatis.spring.annotation.MapperScan;
4+
import org.mybatis.spring.annotation.MapperScans;
5+
import org.springframework.context.annotation.Configuration;
6+
7+
@Configuration
8+
@MapperScans({
9+
@MapperScan,
10+
@MapperScan("org.mybatis.spring.annotation.mapper.ds2")
11+
})
12+
public class AppConfigWithDefaultMapperScans {
13+
}

0 commit comments

Comments
 (0)