Skip to content

Commit

Permalink
Merge pull request #70 from mybatis/pr/40
Browse files Browse the repository at this point in the history
Pr/40 from #40
  • Loading branch information
hazendaz committed May 31, 2015
2 parents 5a84cb8 + 5395d15 commit 5f8ddda
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 34 deletions.
10 changes: 5 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<parent>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-parent</artifactId>
<version>24-SNAPSHOT</version>
<version>24</version>
</parent>

<artifactId>mybatis-spring</artifactId>
Expand Down Expand Up @@ -110,7 +110,7 @@
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.8</version>
<version>3.3.0</version>
<scope>provided</scope>
</dependency>

Expand Down Expand Up @@ -174,7 +174,7 @@
<dependency>
<groupId>org.jboss.byteman</groupId>
<artifactId>byteman-bmunit</artifactId>
<version>3.0.0</version>
<version>3.0.1</version>
<scope>test</scope>
</dependency>

Expand Down Expand Up @@ -306,8 +306,8 @@
</testResources>
</build>

<!-- TODO: Why is this necessary, the dependency is alreayd present at this scope? -->
<!-- this is just a turnaround to Mac compilers -->
<!-- TODO: Why is this necessary, the dependency is already present at this scope? -->
<!-- this is just a turn-around to Mac compilers -->
<profiles>
<profile>
<id>mac-jvm-classloader-issue</id>
Expand Down
10 changes: 8 additions & 2 deletions src/main/java/org/mybatis/spring/annotation/MapperScan.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
*
* @author Michael Lanyon
* @author Eduardo Macarron
*
*
* @since 1.2.0
* @see MapperScannerRegistrar
* @see MapperFactoryBean
Expand Down Expand Up @@ -101,7 +101,7 @@
* within the Spring container.
*/
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

/**
* This property specifies the annotation that the scanner will search for.
* <p>
Expand Down Expand Up @@ -136,4 +136,10 @@
*/
String sqlSessionFactoryRef() default "";

/**
* Specifies a custom MapperFactoryBean to return a mybatis proxy as spring bean.
*
*/
Class<? extends MapperFactoryBean> factoryBean() default MapperFactoryBean.class;

}
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, B
scanner.setBeanNameGenerator(BeanUtils.instantiateClass(generatorClass));
}

Class<? extends MapperFactoryBean> mapperFactoryBeanClass = annoAttrs.getClass("factoryBean");
if (!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) {
scanner.setMapperFactoryBean(BeanUtils.instantiateClass(mapperFactoryBeanClass));
}

scanner.setSqlSessionTemplateBeanName(annoAttrs.getString("sqlSessionTemplateRef"));
scanner.setSqlSessionFactoryBeanName(annoAttrs.getString("sqlSessionFactoryRef"));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner {

private Class<?> markerInterface;

private MapperFactoryBean mapperFactoryBean = new MapperFactoryBean();

public ClassPathMapperScanner(BeanDefinitionRegistry registry) {
super(registry, false);
}
Expand Down Expand Up @@ -102,6 +104,11 @@ public void setSqlSessionFactoryBeanName(String sqlSessionFactoryBeanName) {
this.sqlSessionFactoryBeanName = sqlSessionFactoryBeanName;
}

public void setMapperFactoryBean(MapperFactoryBean mapperFactoryBean) {
this.mapperFactoryBean = (mapperFactoryBean != null ? mapperFactoryBean : new MapperFactoryBean());
}


/**
* Configures parent scanner to search for the right interfaces. It can search
* for all interfaces or just for those that extends a markerInterface or/and
Expand Down Expand Up @@ -177,8 +184,8 @@ private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {

// the mapper interface is the original class of the bean
// but, the actual class of the bean is MapperFactoryBean
definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName());
definition.setBeanClass(MapperFactoryBean.class);
definition.getPropertyValues().add("mapperInterface", definition.getBeanClassName());
definition.setBeanClass(this.mapperFactoryBean.getClass());

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

Expand Down
70 changes: 45 additions & 25 deletions src/main/java/org/mybatis/spring/mapper/MapperFactoryBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
* Note that this factory can only inject <em>interfaces</em>, not concrete classes.
*
* @author Eduardo Macarron
*
*
* @see SqlSessionTemplate
* @version $Id$
*/
Expand All @@ -66,30 +66,6 @@ public MapperFactoryBean(Class<T> mapperInterface) {
public MapperFactoryBean() {
}

/**
* Sets the mapper interface of the MyBatis mapper
*
* @param mapperInterface class of the interface
*/
public void setMapperInterface(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}

/**
* If addToConfig is false the mapper will not be added to MyBatis. This means
* it must have been included in mybatis-config.xml.
* <p>
* If it is true, the mapper will be added to MyBatis in the case it is not already
* registered.
* <p>
* By default addToCofig is true.
*
* @param addToConfig
*/
public void setAddToConfig(boolean addToConfig) {
this.addToConfig = addToConfig;
}

/**
* {@inheritDoc}
*/
Expand Down Expand Up @@ -136,4 +112,48 @@ public boolean isSingleton() {
return true;
}

//------------- mutators --------------

/**
* Sets the mapper interface of the MyBatis mapper
*
* @param mapperInterface class of the interface
*/
public void setMapperInterface(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}

/**
* Return the mapper interface of the MyBatis mapper
*
* @return class of the interface
*/
public Class<T> getMapperInterface() {
return mapperInterface;
}

/**
* If addToConfig is false the mapper will not be added to MyBatis. This means
* it must have been included in mybatis-config.xml.
* <p/>
* If it is true, the mapper will be added to MyBatis in the case it is not already
* registered.
* <p/>
* By default addToCofig is true.
*
* @param addToConfig
*/
public void setAddToConfig(boolean addToConfig) {
this.addToConfig = addToConfig;
}

/**
* Return the flag for addition into MyBatis config.
*
* @return true if the mapper will be added to MyBatis in the case it is not already
* registered.
*/
public boolean isAddToConfig() {
return addToConfig;
}
}
23 changes: 23 additions & 0 deletions src/test/java/org/mybatis/spring/annotation/MapperScanTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package org.mybatis.spring.annotation;

import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import org.junit.After;
Expand All @@ -27,6 +28,7 @@
import org.mybatis.spring.mapper.MapperInterface;
import org.mybatis.spring.mapper.MapperSubinterface;
import org.mybatis.spring.mapper.child.MapperChildInterface;
import org.mybatis.spring.type.DummyMapperFactoryBean;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
Expand Down Expand Up @@ -162,6 +164,22 @@ public void testMarkerInterfaceAndAnnotationScan() {
assertBeanNotLoaded("mapperInterface");
}

@Test
public void testCustomMapperFactoryBean() {
applicationContext.register(AppConfigWithCustomMapperFactoryBean.class);

startContext();

// all interfaces with methods should be loaded
applicationContext.getBean("mapperInterface");
applicationContext.getBean("mapperSubinterface");
applicationContext.getBean("mapperChildInterface");
applicationContext.getBean("annotatedMapper");

assertTrue(DummyMapperFactoryBean.getMapperCount() > 0);

}

@Test
public void testScanWithNameConflict() {
GenericBeanDefinition definition = new GenericBeanDefinition();
Expand Down Expand Up @@ -265,6 +283,11 @@ public static class AppConfigWithSqlSessionFactory {
public static class AppConfigWithNameGenerator {
}

@Configuration
@MapperScan(basePackages = "org.mybatis.spring.mapper", factoryBean = DummyMapperFactoryBean.class)
public static class AppConfigWithCustomMapperFactoryBean {
}

public static class BeanNameGenerator implements org.springframework.beans.factory.support.BeanNameGenerator {

public String generateBeanName(BeanDefinition beanDefinition, BeanDefinitionRegistry definitionRegistry) {
Expand Down
75 changes: 75 additions & 0 deletions src/test/java/org/mybatis/spring/type/DummyMapperFactoryBean.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* Copyright 2010-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mybatis.spring.type;

import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.log4j.Logger;
import org.mybatis.spring.mapper.MapperFactoryBean;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.concurrent.atomic.AtomicInteger;

public class DummyMapperFactoryBean<T> extends MapperFactoryBean<T> {

private static final Logger LOGGER = Logger.getLogger(DummyMapperFactoryBean.class);

private static final AtomicInteger mapperInstanceCount = new AtomicInteger(0);

@Override
protected void checkDaoConfig() {
super.checkDaoConfig();
// make something more
if (isAddToConfig()) {
LOGGER.debug("register mapper for interface : " + getMapperInterface());
}
}

@Override
public T getObject() throws Exception {
MapperFactoryBean<T> mapperFactoryBean = new MapperFactoryBean<T>();
mapperFactoryBean.setMapperInterface(getMapperInterface());
mapperFactoryBean.setAddToConfig(isAddToConfig());
mapperFactoryBean.setSqlSessionFactory(getCustomSessionFactoryForClass());
T object = mapperFactoryBean.getObject();
mapperInstanceCount.incrementAndGet();
return object;
}

private SqlSessionFactory getCustomSessionFactoryForClass() {
// can for example read a custom annotation to set a custom sqlSessionFactory

// just a dummy implementation example
return (SqlSessionFactory) Proxy.newProxyInstance(
SqlSessionFactory.class.getClassLoader(),
new Class[]{SqlSessionFactory.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("getConfiguration".equals(method.getName())) {
return getSqlSession().getConfiguration();
}
// dummy
return null;
}
});
}

public static final int getMapperCount(){
return mapperInstanceCount.get();
}
}

0 comments on commit 5f8ddda

Please sign in to comment.