Skip to content

Commit 5f8ddda

Browse files
committed
Merge pull request #70 from mybatis/pr/40
Pr/40 from #40
2 parents 5a84cb8 + 5395d15 commit 5f8ddda

File tree

7 files changed

+170
-34
lines changed

7 files changed

+170
-34
lines changed

pom.xml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
<parent>
2222
<groupId>org.mybatis</groupId>
2323
<artifactId>mybatis-parent</artifactId>
24-
<version>24-SNAPSHOT</version>
24+
<version>24</version>
2525
</parent>
2626

2727
<artifactId>mybatis-spring</artifactId>
@@ -110,7 +110,7 @@
110110
<dependency>
111111
<groupId>org.mybatis</groupId>
112112
<artifactId>mybatis</artifactId>
113-
<version>3.2.8</version>
113+
<version>3.3.0</version>
114114
<scope>provided</scope>
115115
</dependency>
116116

@@ -174,7 +174,7 @@
174174
<dependency>
175175
<groupId>org.jboss.byteman</groupId>
176176
<artifactId>byteman-bmunit</artifactId>
177-
<version>3.0.0</version>
177+
<version>3.0.1</version>
178178
<scope>test</scope>
179179
</dependency>
180180

@@ -306,8 +306,8 @@
306306
</testResources>
307307
</build>
308308

309-
<!-- TODO: Why is this necessary, the dependency is alreayd present at this scope? -->
310-
<!-- this is just a turnaround to Mac compilers -->
309+
<!-- TODO: Why is this necessary, the dependency is already present at this scope? -->
310+
<!-- this is just a turn-around to Mac compilers -->
311311
<profiles>
312312
<profile>
313313
<id>mac-jvm-classloader-issue</id>

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
*
6262
* @author Michael Lanyon
6363
* @author Eduardo Macarron
64-
*
64+
*
6565
* @since 1.2.0
6666
* @see MapperScannerRegistrar
6767
* @see MapperFactoryBean
@@ -101,7 +101,7 @@
101101
* within the Spring container.
102102
*/
103103
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
104-
104+
105105
/**
106106
* This property specifies the annotation that the scanner will search for.
107107
* <p>
@@ -136,4 +136,10 @@
136136
*/
137137
String sqlSessionFactoryRef() default "";
138138

139+
/**
140+
* Specifies a custom MapperFactoryBean to return a mybatis proxy as spring bean.
141+
*
142+
*/
143+
Class<? extends MapperFactoryBean> factoryBean() default MapperFactoryBean.class;
144+
139145
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, B
7979
scanner.setBeanNameGenerator(BeanUtils.instantiateClass(generatorClass));
8080
}
8181

82+
Class<? extends MapperFactoryBean> mapperFactoryBeanClass = annoAttrs.getClass("factoryBean");
83+
if (!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) {
84+
scanner.setMapperFactoryBean(BeanUtils.instantiateClass(mapperFactoryBeanClass));
85+
}
86+
8287
scanner.setSqlSessionTemplateBeanName(annoAttrs.getString("sqlSessionTemplateRef"));
8388
scanner.setSqlSessionFactoryBeanName(annoAttrs.getString("sqlSessionFactoryRef"));
8489

src/main/java/org/mybatis/spring/mapper/ClassPathMapperScanner.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner {
7070

7171
private Class<?> markerInterface;
7272

73+
private MapperFactoryBean mapperFactoryBean = new MapperFactoryBean();
74+
7375
public ClassPathMapperScanner(BeanDefinitionRegistry registry) {
7476
super(registry, false);
7577
}
@@ -102,6 +104,11 @@ public void setSqlSessionFactoryBeanName(String sqlSessionFactoryBeanName) {
102104
this.sqlSessionFactoryBeanName = sqlSessionFactoryBeanName;
103105
}
104106

107+
public void setMapperFactoryBean(MapperFactoryBean mapperFactoryBean) {
108+
this.mapperFactoryBean = (mapperFactoryBean != null ? mapperFactoryBean : new MapperFactoryBean());
109+
}
110+
111+
105112
/**
106113
* Configures parent scanner to search for the right interfaces. It can search
107114
* for all interfaces or just for those that extends a markerInterface or/and
@@ -177,8 +184,8 @@ private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
177184

178185
// the mapper interface is the original class of the bean
179186
// but, the actual class of the bean is MapperFactoryBean
180-
definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName());
181-
definition.setBeanClass(MapperFactoryBean.class);
187+
definition.getPropertyValues().add("mapperInterface", definition.getBeanClassName());
188+
definition.setBeanClass(this.mapperFactoryBean.getClass());
182189

183190
definition.getPropertyValues().add("addToConfig", this.addToConfig);
184191

src/main/java/org/mybatis/spring/mapper/MapperFactoryBean.java

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
* Note that this factory can only inject <em>interfaces</em>, not concrete classes.
4949
*
5050
* @author Eduardo Macarron
51-
*
51+
*
5252
* @see SqlSessionTemplate
5353
* @version $Id$
5454
*/
@@ -66,30 +66,6 @@ public MapperFactoryBean(Class<T> mapperInterface) {
6666
public MapperFactoryBean() {
6767
}
6868

69-
/**
70-
* Sets the mapper interface of the MyBatis mapper
71-
*
72-
* @param mapperInterface class of the interface
73-
*/
74-
public void setMapperInterface(Class<T> mapperInterface) {
75-
this.mapperInterface = mapperInterface;
76-
}
77-
78-
/**
79-
* If addToConfig is false the mapper will not be added to MyBatis. This means
80-
* it must have been included in mybatis-config.xml.
81-
* <p>
82-
* If it is true, the mapper will be added to MyBatis in the case it is not already
83-
* registered.
84-
* <p>
85-
* By default addToCofig is true.
86-
*
87-
* @param addToConfig
88-
*/
89-
public void setAddToConfig(boolean addToConfig) {
90-
this.addToConfig = addToConfig;
91-
}
92-
9369
/**
9470
* {@inheritDoc}
9571
*/
@@ -136,4 +112,48 @@ public boolean isSingleton() {
136112
return true;
137113
}
138114

115+
//------------- mutators --------------
116+
117+
/**
118+
* Sets the mapper interface of the MyBatis mapper
119+
*
120+
* @param mapperInterface class of the interface
121+
*/
122+
public void setMapperInterface(Class<T> mapperInterface) {
123+
this.mapperInterface = mapperInterface;
124+
}
125+
126+
/**
127+
* Return the mapper interface of the MyBatis mapper
128+
*
129+
* @return class of the interface
130+
*/
131+
public Class<T> getMapperInterface() {
132+
return mapperInterface;
133+
}
134+
135+
/**
136+
* If addToConfig is false the mapper will not be added to MyBatis. This means
137+
* it must have been included in mybatis-config.xml.
138+
* <p/>
139+
* If it is true, the mapper will be added to MyBatis in the case it is not already
140+
* registered.
141+
* <p/>
142+
* By default addToCofig is true.
143+
*
144+
* @param addToConfig
145+
*/
146+
public void setAddToConfig(boolean addToConfig) {
147+
this.addToConfig = addToConfig;
148+
}
149+
150+
/**
151+
* Return the flag for addition into MyBatis config.
152+
*
153+
* @return true if the mapper will be added to MyBatis in the case it is not already
154+
* registered.
155+
*/
156+
public boolean isAddToConfig() {
157+
return addToConfig;
158+
}
139159
}

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.mybatis.spring.annotation;
1717

1818
import static org.junit.Assert.assertSame;
19+
import static org.junit.Assert.assertTrue;
1920
import static org.junit.Assert.fail;
2021

2122
import org.junit.After;
@@ -27,6 +28,7 @@
2728
import org.mybatis.spring.mapper.MapperInterface;
2829
import org.mybatis.spring.mapper.MapperSubinterface;
2930
import org.mybatis.spring.mapper.child.MapperChildInterface;
31+
import org.mybatis.spring.type.DummyMapperFactoryBean;
3032
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
3133
import org.springframework.beans.factory.config.BeanDefinition;
3234
import org.springframework.beans.factory.config.ConstructorArgumentValues;
@@ -162,6 +164,22 @@ public void testMarkerInterfaceAndAnnotationScan() {
162164
assertBeanNotLoaded("mapperInterface");
163165
}
164166

167+
@Test
168+
public void testCustomMapperFactoryBean() {
169+
applicationContext.register(AppConfigWithCustomMapperFactoryBean.class);
170+
171+
startContext();
172+
173+
// all interfaces with methods should be loaded
174+
applicationContext.getBean("mapperInterface");
175+
applicationContext.getBean("mapperSubinterface");
176+
applicationContext.getBean("mapperChildInterface");
177+
applicationContext.getBean("annotatedMapper");
178+
179+
assertTrue(DummyMapperFactoryBean.getMapperCount() > 0);
180+
181+
}
182+
165183
@Test
166184
public void testScanWithNameConflict() {
167185
GenericBeanDefinition definition = new GenericBeanDefinition();
@@ -265,6 +283,11 @@ public static class AppConfigWithSqlSessionFactory {
265283
public static class AppConfigWithNameGenerator {
266284
}
267285

286+
@Configuration
287+
@MapperScan(basePackages = "org.mybatis.spring.mapper", factoryBean = DummyMapperFactoryBean.class)
288+
public static class AppConfigWithCustomMapperFactoryBean {
289+
}
290+
268291
public static class BeanNameGenerator implements org.springframework.beans.factory.support.BeanNameGenerator {
269292

270293
public String generateBeanName(BeanDefinition beanDefinition, BeanDefinitionRegistry definitionRegistry) {
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**
2+
* Copyright 2010-2015 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+
* http://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.spring.type;
17+
18+
import org.apache.ibatis.session.SqlSessionFactory;
19+
import org.apache.log4j.Logger;
20+
import org.mybatis.spring.mapper.MapperFactoryBean;
21+
22+
import java.lang.reflect.InvocationHandler;
23+
import java.lang.reflect.Method;
24+
import java.lang.reflect.Proxy;
25+
import java.util.concurrent.atomic.AtomicInteger;
26+
27+
public class DummyMapperFactoryBean<T> extends MapperFactoryBean<T> {
28+
29+
private static final Logger LOGGER = Logger.getLogger(DummyMapperFactoryBean.class);
30+
31+
private static final AtomicInteger mapperInstanceCount = new AtomicInteger(0);
32+
33+
@Override
34+
protected void checkDaoConfig() {
35+
super.checkDaoConfig();
36+
// make something more
37+
if (isAddToConfig()) {
38+
LOGGER.debug("register mapper for interface : " + getMapperInterface());
39+
}
40+
}
41+
42+
@Override
43+
public T getObject() throws Exception {
44+
MapperFactoryBean<T> mapperFactoryBean = new MapperFactoryBean<T>();
45+
mapperFactoryBean.setMapperInterface(getMapperInterface());
46+
mapperFactoryBean.setAddToConfig(isAddToConfig());
47+
mapperFactoryBean.setSqlSessionFactory(getCustomSessionFactoryForClass());
48+
T object = mapperFactoryBean.getObject();
49+
mapperInstanceCount.incrementAndGet();
50+
return object;
51+
}
52+
53+
private SqlSessionFactory getCustomSessionFactoryForClass() {
54+
// can for example read a custom annotation to set a custom sqlSessionFactory
55+
56+
// just a dummy implementation example
57+
return (SqlSessionFactory) Proxy.newProxyInstance(
58+
SqlSessionFactory.class.getClassLoader(),
59+
new Class[]{SqlSessionFactory.class},
60+
new InvocationHandler() {
61+
@Override
62+
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
63+
if ("getConfiguration".equals(method.getName())) {
64+
return getSqlSession().getConfiguration();
65+
}
66+
// dummy
67+
return null;
68+
}
69+
});
70+
}
71+
72+
public static final int getMapperCount(){
73+
return mapperInstanceCount.get();
74+
}
75+
}

0 commit comments

Comments
 (0)