From 7f7ef3d5c932edc0ca263b811cdf0f88347ac575 Mon Sep 17 00:00:00 2001 From: lixiaopeng Date: Thu, 6 Jul 2023 15:37:18 +0800 Subject: [PATCH 01/13] fix issue 548. add ComponentScan.Filter[] excludeFilters() to @MapperScan,people can use excludeFilters to customized mapper excludeFilters. --- pom.xml | 6 ++ .../mybatis/spring/annotation/MapperScan.java | 7 ++ .../annotation/MapperScannerRegistrar.java | 53 ++++++++++ .../spring/mapper/ClassPathMapperScanner.java | 14 +++ .../mapper/MapperScannerConfigurer.java | 10 ++ .../spring/scan/filter/ScanFilterTest.java | 99 +++++++++++++++++++ .../spring/scan/filter/config/AppConfig.java | 46 +++++++++ .../filter/customfilter/AnnoTypeFilter.java | 9 ++ .../filter/customfilter/CustomTypeFilter.java | 14 +++ .../filter/customfilter/ExcludeMaker.java | 5 + .../commonsource/AnnoExcludeMapper.java | 8 ++ .../commonsource/AssignableMapper.java | 7 ++ .../commonsource/CommonDataSourceMapper.java | 6 ++ .../datasource1/DataSource1Mapper.java | 6 ++ .../datasource2/DataSource2Mapper.java | 6 ++ 15 files changed, 296 insertions(+) create mode 100644 src/test/java/org/mybatis/spring/scan/filter/ScanFilterTest.java create mode 100644 src/test/java/org/mybatis/spring/scan/filter/config/AppConfig.java create mode 100644 src/test/java/org/mybatis/spring/scan/filter/customfilter/AnnoTypeFilter.java create mode 100644 src/test/java/org/mybatis/spring/scan/filter/customfilter/CustomTypeFilter.java create mode 100644 src/test/java/org/mybatis/spring/scan/filter/customfilter/ExcludeMaker.java create mode 100644 src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AnnoExcludeMapper.java create mode 100644 src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AssignableMapper.java create mode 100644 src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/CommonDataSourceMapper.java create mode 100644 src/test/java/org/mybatis/spring/scan/filter/datasource/datasource1/DataSource1Mapper.java create mode 100644 src/test/java/org/mybatis/spring/scan/filter/datasource/datasource2/DataSource2Mapper.java diff --git a/pom.xml b/pom.xml index f910678b1e..b2766c3ea3 100644 --- a/pom.xml +++ b/pom.xml @@ -313,6 +313,12 @@ 6.0.0 test + + org.aspectj + aspectjweaver + 1.9.19 + true + diff --git a/src/main/java/org/mybatis/spring/annotation/MapperScan.java b/src/main/java/org/mybatis/spring/annotation/MapperScan.java index 78c0d9b0bf..4be73792a6 100644 --- a/src/main/java/org/mybatis/spring/annotation/MapperScan.java +++ b/src/main/java/org/mybatis/spring/annotation/MapperScan.java @@ -27,6 +27,7 @@ import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanNameGenerator; +import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Import; import org.springframework.core.annotation.AliasFor; @@ -185,4 +186,10 @@ */ String defaultScope() default AbstractBeanDefinition.SCOPE_DEFAULT; + /** + * Specifies which types are not eligible for mapper scanning. + */ + ComponentScan.Filter[] excludeFilters() default {}; + + } diff --git a/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java b/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java index cde801d739..1f7d4a5f7b 100644 --- a/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java +++ b/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.regex.Pattern; import java.util.stream.Collectors; import org.mybatis.spring.mapper.ClassPathMapperScanner; @@ -31,10 +32,13 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.context.ResourceLoaderAware; +import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.AnnotationMetadata; +import org.springframework.core.type.filter.*; +import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; @@ -54,6 +58,7 @@ */ public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware { + private ResourceLoader resourceLoader; /** * {@inheritDoc} * @@ -63,6 +68,7 @@ public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, Re @Deprecated public void setResourceLoader(ResourceLoader resourceLoader) { // NOP + this.resourceLoader = resourceLoader; } /** @@ -126,6 +132,11 @@ void registerBeanDefinitions(AnnotationMetadata annoMeta, AnnotationAttributes a basePackages.add(getDefaultBasePackage(annoMeta)); } + AnnotationAttributes[] excludeFilterArray = annoAttrs.getAnnotationArray("excludeFilters"); + for (AnnotationAttributes excludeFilters : excludeFilterArray) { + builder.addPropertyValue("excludeFilters", typeFiltersFor(excludeFilters)); + } + String lazyInitialization = annoAttrs.getString("lazyInitialization"); if (StringUtils.hasText(lazyInitialization)) { builder.addPropertyValue("lazyInitialization", lazyInitialization); @@ -145,6 +156,48 @@ void registerBeanDefinitions(AnnotationMetadata annoMeta, AnnotationAttributes a } + private List typeFiltersFor(AnnotationAttributes filterAttributes) { + + List typeFilters = new ArrayList<>(); + FilterType filterType = filterAttributes.getEnum("type"); + + for (Class filterClass : filterAttributes.getClassArray("value")) { + switch (filterType) { + case ANNOTATION: + Assert.isAssignable(Annotation.class, filterClass, + "An error occured when processing a @ComponentScan " + "ANNOTATION type filter: "); + @SuppressWarnings("unchecked") + Class annoClass = (Class) filterClass; + typeFilters.add(new AnnotationTypeFilter(annoClass)); + break; + case ASSIGNABLE_TYPE: + typeFilters.add(new AssignableTypeFilter(filterClass)); + break; + case CUSTOM: + Assert.isAssignable(TypeFilter.class, filterClass, + "An error occured when processing a @ComponentScan " + "CUSTOM type filter: "); + typeFilters.add(BeanUtils.instantiateClass(filterClass, TypeFilter.class)); + break; + default: + throw new IllegalArgumentException("Unknown filter type " + filterType); + } + } + + String[] expressionArray = filterAttributes.getStringArray("pattern"); + for (String expression : expressionArray) { + String rawName = filterType.toString(); + if ("REGEX".equals(rawName)) { + typeFilters.add(new RegexPatternTypeFilter(Pattern.compile(expression))); + } else if ("ASPECTJ".equals(rawName)) { + typeFilters.add(new AspectJTypeFilter(expression, this.resourceLoader.getClassLoader())); + } else { + throw new IllegalArgumentException("Unknown filter type " + filterType); + } + } + return typeFilters; + } + + private static String generateBaseBeanName(AnnotationMetadata importingClassMetadata, int index) { return importingClassMetadata.getClassName() + "#" + MapperScannerRegistrar.class.getSimpleName() + "#" + index; } diff --git a/src/main/java/org/mybatis/spring/mapper/ClassPathMapperScanner.java b/src/main/java/org/mybatis/spring/mapper/ClassPathMapperScanner.java index 617095f7f8..5956b5bb3b 100644 --- a/src/main/java/org/mybatis/spring/mapper/ClassPathMapperScanner.java +++ b/src/main/java/org/mybatis/spring/mapper/ClassPathMapperScanner.java @@ -17,6 +17,7 @@ import java.lang.annotation.Annotation; import java.util.Arrays; +import java.util.List; import java.util.Optional; import java.util.Set; @@ -39,6 +40,7 @@ import org.springframework.core.NativeDetector; import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.core.type.filter.AssignableTypeFilter; +import org.springframework.core.type.filter.TypeFilter; import org.springframework.util.StringUtils; /** @@ -84,6 +86,7 @@ public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner { private Class mapperFactoryBeanClass = MapperFactoryBean.class; private String defaultScope; + private List excludeFilters; public ClassPathMapperScanner(BeanDefinitionRegistry registry) { super(registry, false); @@ -133,6 +136,10 @@ public void setMarkerInterface(Class markerInterface) { this.markerInterface = markerInterface; } + public void setExcludeFilters(List excludeFilters) { + this.excludeFilters = excludeFilters; + } + public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { this.sqlSessionFactory = sqlSessionFactory; } @@ -218,6 +225,13 @@ protected boolean matchClassName(String className) { String className = metadataReader.getClassMetadata().getClassName(); return className.endsWith("package-info"); }); + + // exclude types declared by MapperScan.excludeFilters + if (excludeFilters != null && excludeFilters.size() > 0) { + for (TypeFilter excludeFilter : excludeFilters) { + addExcludeFilter(excludeFilter); + } + } } /** diff --git a/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java b/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java index 5b10b71192..30b7724863 100644 --- a/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java +++ b/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java @@ -18,6 +18,7 @@ import static org.springframework.util.Assert.notNull; import java.lang.annotation.Annotation; +import java.util.List; import java.util.Map; import java.util.Optional; @@ -39,6 +40,7 @@ import org.springframework.context.ApplicationContextAware; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.Environment; +import org.springframework.core.type.filter.TypeFilter; import org.springframework.util.StringUtils; /** @@ -109,6 +111,9 @@ public class MapperScannerConfigurer private Class markerInterface; + + private List excludeFilters; + private Class mapperFactoryBeanClass; private ApplicationContext applicationContext; @@ -191,6 +196,10 @@ public void setMarkerInterface(Class superClass) { this.markerInterface = superClass; } + public void setExcludeFilters(List excludeFilters) { + this.excludeFilters = excludeFilters; + } + /** * Specifies which {@code SqlSessionTemplate} to use in the case that there is more than one in the spring context. * Usually this is only needed when you have more than one datasource. @@ -364,6 +373,7 @@ public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { scanner.setAddToConfig(this.addToConfig); scanner.setAnnotationClass(this.annotationClass); scanner.setMarkerInterface(this.markerInterface); + scanner.setExcludeFilters(this.excludeFilters); scanner.setSqlSessionFactory(this.sqlSessionFactory); scanner.setSqlSessionTemplate(this.sqlSessionTemplate); scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName); diff --git a/src/test/java/org/mybatis/spring/scan/filter/ScanFilterTest.java b/src/test/java/org/mybatis/spring/scan/filter/ScanFilterTest.java new file mode 100644 index 0000000000..cf6fe0fd67 --- /dev/null +++ b/src/test/java/org/mybatis/spring/scan/filter/ScanFilterTest.java @@ -0,0 +1,99 @@ +package org.mybatis.spring.scan.filter; + +import com.mockrunner.mock.jdbc.MockDataSource; +import org.junit.jupiter.api.Test; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.scan.filter.config.AppConfig; +import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +// test the function of excludeFilters in @MapperScan +public class ScanFilterTest { + + private AnnotationConfigApplicationContext applicationContext; + + + @Test + void testCustomScanFilter() { + startContext(AppConfig.CustomFilterConfig.class); + // use org.mybatis.spring.scan.filter.datasource as basePackages and exclude package datasource2 by MapperScan.excludeFilters + // mapper in package datasource2 will not be registered to beanFactory + assertThat(applicationContext.containsBean("dataSource2Mapper")).isEqualTo(false); + + // mapper in package datasource except datasource2 will be registered to beanFactory correctly. + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isEqualTo(true); + assertThat(applicationContext.containsBean("dataSource1Mapper")).isEqualTo(true); + } + + @Test + void testAnnoScanFilter() { + startContext(AppConfig.AnnoFilterConfig.class); + + // use @AnnoTypeFilter to exclude mapper + assertThat(applicationContext.containsBean("annoExcludeMapper")).isEqualTo(false); + + // mapper in package datasource except datasource2 will be registered to beanFactory correctly. + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isEqualTo(true); + assertThat(applicationContext.containsBean("dataSource1Mapper")).isEqualTo(true); + assertThat(applicationContext.containsBean("dataSource2Mapper")).isEqualTo(true); + } + + + @Test + void testAssignableScanFilter() { + startContext(AppConfig.AssignableFilterConfig.class); + + // exclude AssignableMapper by AssignableFilter + assertThat(applicationContext.containsBean("assignableMapper")).isEqualTo(false); + + // mapper in package datasource except datasource2 will be registered to beanFactory correctly. + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isEqualTo(true); + assertThat(applicationContext.containsBean("dataSource1Mapper")).isEqualTo(true); + assertThat(applicationContext.containsBean("dataSource2Mapper")).isEqualTo(true); + } + + @Test + void testRegexScanFilter() { + startContext(AppConfig.RegexFilterConfig.class); + + // exclude package datasource1 by Regex + assertThat(applicationContext.containsBean("dataSource1Mapper")).isEqualTo(false); + + // mapper in package datasource except datasource1 will be registered to beanFactory correctly. + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isEqualTo(true); + assertThat(applicationContext.containsBean("dataSource2Mapper")).isEqualTo(true); + } + + @Test + void testAspectJScanFilter() { + + startContext(AppConfig.AspectJFilterConfig.class); + + // exclude dataSource1Mapper by AspectJ + assertThat(applicationContext.containsBean("dataSource1Mapper")).isEqualTo(false); + + // mapper in package datasource except datasource1 will be registered to beanFactory correctly. + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isEqualTo(true); + assertThat(applicationContext.containsBean("dataSource2Mapper")).isEqualTo(true); + } + + + private void startContext(Class config) { + applicationContext = new AnnotationConfigApplicationContext(); + // use @MapperScan with excludeFilters in AppConfig.class + applicationContext.register(config); + setupSqlSessionFactory("sqlSessionFactory"); + applicationContext.refresh(); + applicationContext.start(); + } + + + private void setupSqlSessionFactory(String name) { + GenericBeanDefinition definition = new GenericBeanDefinition(); + definition.setBeanClass(SqlSessionFactoryBean.class); + definition.getPropertyValues().add("dataSource", new MockDataSource()); + applicationContext.registerBeanDefinition(name, definition); + } +} diff --git a/src/test/java/org/mybatis/spring/scan/filter/config/AppConfig.java b/src/test/java/org/mybatis/spring/scan/filter/config/AppConfig.java new file mode 100644 index 0000000000..c0c3bd1458 --- /dev/null +++ b/src/test/java/org/mybatis/spring/scan/filter/config/AppConfig.java @@ -0,0 +1,46 @@ +package org.mybatis.spring.scan.filter.config; + +import org.mybatis.spring.annotation.MapperScan; +import org.mybatis.spring.scan.filter.customfilter.AnnoTypeFilter; +import org.mybatis.spring.scan.filter.customfilter.ExcludeMaker; +import org.mybatis.spring.scan.filter.customfilter.CustomTypeFilter; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.FilterType; + + +public class AppConfig { + + + @MapperScan(basePackages = "org.mybatis.spring.scan.filter.datasource", + excludeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM, classes = CustomTypeFilter.class)}) + public static class CustomFilterConfig { + + } + + @MapperScan(basePackages = "org.mybatis.spring.scan.filter.datasource", + excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = AnnoTypeFilter.class)}) + public static class AnnoFilterConfig { + + } + + @MapperScan(basePackages = "org.mybatis.spring.scan.filter.datasource", + excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ExcludeMaker.class)}) + public static class AssignableFilterConfig { + + } + + @MapperScan(basePackages = "org.mybatis.spring.scan.filter.datasource", + excludeFilters = {@ComponentScan.Filter(type = FilterType.REGEX, + pattern = "org\\.mybatis\\.spring\\.scan\\.filter\\.datasource\\.datasource1\\..*")}) + public static class RegexFilterConfig { + + } + + @MapperScan(basePackages = "org.mybatis.spring.scan.filter.datasource", + excludeFilters = {@ComponentScan.Filter(type = FilterType.ASPECTJ, + pattern = "*..DataSource1Mapper")}) + public static class AspectJFilterConfig { + + } +} + diff --git a/src/test/java/org/mybatis/spring/scan/filter/customfilter/AnnoTypeFilter.java b/src/test/java/org/mybatis/spring/scan/filter/customfilter/AnnoTypeFilter.java new file mode 100644 index 0000000000..63e174db9f --- /dev/null +++ b/src/test/java/org/mybatis/spring/scan/filter/customfilter/AnnoTypeFilter.java @@ -0,0 +1,9 @@ +package org.mybatis.spring.scan.filter.customfilter; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +@Documented +public @interface AnnoTypeFilter { +} diff --git a/src/test/java/org/mybatis/spring/scan/filter/customfilter/CustomTypeFilter.java b/src/test/java/org/mybatis/spring/scan/filter/customfilter/CustomTypeFilter.java new file mode 100644 index 0000000000..64c70fc8d0 --- /dev/null +++ b/src/test/java/org/mybatis/spring/scan/filter/customfilter/CustomTypeFilter.java @@ -0,0 +1,14 @@ +package org.mybatis.spring.scan.filter.customfilter; + +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.MetadataReaderFactory; +import org.springframework.core.type.filter.TypeFilter; + +import java.io.IOException; + +public class CustomTypeFilter implements TypeFilter { + @Override + public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { + return metadataReader.getClassMetadata().getClassName().contains("datasource2"); + } +} diff --git a/src/test/java/org/mybatis/spring/scan/filter/customfilter/ExcludeMaker.java b/src/test/java/org/mybatis/spring/scan/filter/customfilter/ExcludeMaker.java new file mode 100644 index 0000000000..b4d871e7da --- /dev/null +++ b/src/test/java/org/mybatis/spring/scan/filter/customfilter/ExcludeMaker.java @@ -0,0 +1,5 @@ +package org.mybatis.spring.scan.filter.customfilter; + + +public interface ExcludeMaker { +} diff --git a/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AnnoExcludeMapper.java b/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AnnoExcludeMapper.java new file mode 100644 index 0000000000..a47480f5c7 --- /dev/null +++ b/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AnnoExcludeMapper.java @@ -0,0 +1,8 @@ +package org.mybatis.spring.scan.filter.datasource.commonsource; + +import org.apache.ibatis.annotations.Mapper; +import org.mybatis.spring.scan.filter.customfilter.AnnoTypeFilter; + +@AnnoTypeFilter +public interface AnnoExcludeMapper extends Mapper { +} diff --git a/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AssignableMapper.java b/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AssignableMapper.java new file mode 100644 index 0000000000..8a41645467 --- /dev/null +++ b/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AssignableMapper.java @@ -0,0 +1,7 @@ +package org.mybatis.spring.scan.filter.datasource.commonsource; + +import org.apache.ibatis.annotations.Mapper; +import org.mybatis.spring.scan.filter.customfilter.ExcludeMaker; + +public interface AssignableMapper extends ExcludeMaker,Mapper { +} diff --git a/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/CommonDataSourceMapper.java b/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/CommonDataSourceMapper.java new file mode 100644 index 0000000000..048c706d53 --- /dev/null +++ b/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/CommonDataSourceMapper.java @@ -0,0 +1,6 @@ +package org.mybatis.spring.scan.filter.datasource.commonsource; + +import org.apache.ibatis.annotations.Mapper; + +public interface CommonDataSourceMapper extends Mapper { +} diff --git a/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource1/DataSource1Mapper.java b/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource1/DataSource1Mapper.java new file mode 100644 index 0000000000..79c47e8e9f --- /dev/null +++ b/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource1/DataSource1Mapper.java @@ -0,0 +1,6 @@ +package org.mybatis.spring.scan.filter.datasource.datasource1; + +import org.apache.ibatis.annotations.Mapper; + +public interface DataSource1Mapper extends Mapper { +} diff --git a/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource2/DataSource2Mapper.java b/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource2/DataSource2Mapper.java new file mode 100644 index 0000000000..154fe3fe32 --- /dev/null +++ b/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource2/DataSource2Mapper.java @@ -0,0 +1,6 @@ +package org.mybatis.spring.scan.filter.datasource.datasource2; + +import org.apache.ibatis.annotations.Mapper; + +public interface DataSource2Mapper extends Mapper { +} From cc31d4a4843055e8df6bcd31d0c616f6f5eb3e93 Mon Sep 17 00:00:00 2001 From: lixiaopeng Date: Sat, 8 Jul 2023 17:39:40 +0800 Subject: [PATCH 02/13] optimize imports --- .../filter/datasource/commonsource/AnnoExcludeMapper.java | 3 +-- .../scan/filter/datasource/commonsource/AssignableMapper.java | 3 +-- .../datasource/commonsource/CommonDataSourceMapper.java | 3 +-- .../scan/filter/datasource/datasource1/DataSource1Mapper.java | 4 +--- .../scan/filter/datasource/datasource2/DataSource2Mapper.java | 4 +--- 5 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AnnoExcludeMapper.java b/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AnnoExcludeMapper.java index a47480f5c7..64cc3ba15c 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AnnoExcludeMapper.java +++ b/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AnnoExcludeMapper.java @@ -1,8 +1,7 @@ package org.mybatis.spring.scan.filter.datasource.commonsource; -import org.apache.ibatis.annotations.Mapper; import org.mybatis.spring.scan.filter.customfilter.AnnoTypeFilter; @AnnoTypeFilter -public interface AnnoExcludeMapper extends Mapper { +public interface AnnoExcludeMapper { } diff --git a/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AssignableMapper.java b/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AssignableMapper.java index 8a41645467..cc2cc05870 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AssignableMapper.java +++ b/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AssignableMapper.java @@ -1,7 +1,6 @@ package org.mybatis.spring.scan.filter.datasource.commonsource; -import org.apache.ibatis.annotations.Mapper; import org.mybatis.spring.scan.filter.customfilter.ExcludeMaker; -public interface AssignableMapper extends ExcludeMaker,Mapper { +public interface AssignableMapper extends ExcludeMaker { } diff --git a/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/CommonDataSourceMapper.java b/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/CommonDataSourceMapper.java index 048c706d53..c132943f38 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/CommonDataSourceMapper.java +++ b/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/CommonDataSourceMapper.java @@ -1,6 +1,5 @@ package org.mybatis.spring.scan.filter.datasource.commonsource; -import org.apache.ibatis.annotations.Mapper; -public interface CommonDataSourceMapper extends Mapper { +public interface CommonDataSourceMapper { } diff --git a/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource1/DataSource1Mapper.java b/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource1/DataSource1Mapper.java index 79c47e8e9f..b89298dba5 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource1/DataSource1Mapper.java +++ b/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource1/DataSource1Mapper.java @@ -1,6 +1,4 @@ package org.mybatis.spring.scan.filter.datasource.datasource1; -import org.apache.ibatis.annotations.Mapper; - -public interface DataSource1Mapper extends Mapper { +public interface DataSource1Mapper { } diff --git a/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource2/DataSource2Mapper.java b/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource2/DataSource2Mapper.java index 154fe3fe32..6a18893bfa 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource2/DataSource2Mapper.java +++ b/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource2/DataSource2Mapper.java @@ -1,6 +1,4 @@ package org.mybatis.spring.scan.filter.datasource.datasource2; -import org.apache.ibatis.annotations.Mapper; - -public interface DataSource2Mapper extends Mapper { +public interface DataSource2Mapper { } From c711ce48b98df43d4cd58ff1e8ca3e0b832ffa8c Mon Sep 17 00:00:00 2001 From: lixiaopeng Date: Sun, 9 Jul 2023 15:16:03 +0800 Subject: [PATCH 03/13] 1.remove @Deprecated on method setResourceLoader. 2.add comment. --- .../annotation/MapperScannerRegistrar.java | 4 ---- .../mapper/MapperScannerConfigurer.java | 9 ++++++++- .../spring/scan/filter/ScanFilterTest.java | 19 ++++++++++++++++++- .../spring/scan/filter/config/AppConfig.java | 15 +++++++++++++++ .../filter/customfilter/AnnoTypeFilter.java | 15 +++++++++++++++ .../filter/customfilter/CustomTypeFilter.java | 15 +++++++++++++++ .../filter/customfilter/ExcludeMaker.java | 15 +++++++++++++++ .../commonsource/AnnoExcludeMapper.java | 15 +++++++++++++++ .../commonsource/AssignableMapper.java | 15 +++++++++++++++ .../commonsource/CommonDataSourceMapper.java | 15 +++++++++++++++ .../datasource1/DataSource1Mapper.java | 15 +++++++++++++++ .../datasource2/DataSource2Mapper.java | 15 +++++++++++++++ 12 files changed, 161 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java b/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java index 6f4ee1aefb..a7f194c6a6 100644 --- a/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java +++ b/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java @@ -61,13 +61,9 @@ public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, Re private ResourceLoader resourceLoader; /** * {@inheritDoc} - * - * @deprecated Since 2.0.2, this method not used never. */ @Override - @Deprecated public void setResourceLoader(ResourceLoader resourceLoader) { - // NOP this.resourceLoader = resourceLoader; } diff --git a/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java b/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java index 30b7724863..bfef6ed6b3 100644 --- a/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java +++ b/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java @@ -111,7 +111,6 @@ public class MapperScannerConfigurer private Class markerInterface; - private List excludeFilters; private Class mapperFactoryBeanClass; @@ -196,6 +195,14 @@ public void setMarkerInterface(Class superClass) { this.markerInterface = superClass; } + /** + * Specifies which types are not eligible for the mapper scanner. + *

+ * The scanner will exclude types that define with excludeFilters. + * + * @param excludeFilters + * list of TypeFilter + */ public void setExcludeFilters(List excludeFilters) { this.excludeFilters = excludeFilters; } diff --git a/src/test/java/org/mybatis/spring/scan/filter/ScanFilterTest.java b/src/test/java/org/mybatis/spring/scan/filter/ScanFilterTest.java index cf6fe0fd67..9f8cba64d7 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/ScanFilterTest.java +++ b/src/test/java/org/mybatis/spring/scan/filter/ScanFilterTest.java @@ -1,3 +1,18 @@ +/* + * Copyright 2010-2023 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 + * + * https://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.scan.filter; import com.mockrunner.mock.jdbc.MockDataSource; @@ -9,7 +24,9 @@ import static org.assertj.core.api.Assertions.assertThat; -// test the function of excludeFilters in @MapperScan +/** + * test the function of excludeFilters in @MapperScan + */ public class ScanFilterTest { private AnnotationConfigApplicationContext applicationContext; diff --git a/src/test/java/org/mybatis/spring/scan/filter/config/AppConfig.java b/src/test/java/org/mybatis/spring/scan/filter/config/AppConfig.java index c0c3bd1458..1143bf6684 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/config/AppConfig.java +++ b/src/test/java/org/mybatis/spring/scan/filter/config/AppConfig.java @@ -1,3 +1,18 @@ +/* + * Copyright 2010-2023 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 + * + * https://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.scan.filter.config; import org.mybatis.spring.annotation.MapperScan; diff --git a/src/test/java/org/mybatis/spring/scan/filter/customfilter/AnnoTypeFilter.java b/src/test/java/org/mybatis/spring/scan/filter/customfilter/AnnoTypeFilter.java index 63e174db9f..d833d5895c 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/customfilter/AnnoTypeFilter.java +++ b/src/test/java/org/mybatis/spring/scan/filter/customfilter/AnnoTypeFilter.java @@ -1,3 +1,18 @@ +/* + * Copyright 2010-2023 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 + * + * https://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.scan.filter.customfilter; import java.lang.annotation.*; diff --git a/src/test/java/org/mybatis/spring/scan/filter/customfilter/CustomTypeFilter.java b/src/test/java/org/mybatis/spring/scan/filter/customfilter/CustomTypeFilter.java index 64c70fc8d0..3cdf9e0ab4 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/customfilter/CustomTypeFilter.java +++ b/src/test/java/org/mybatis/spring/scan/filter/customfilter/CustomTypeFilter.java @@ -1,3 +1,18 @@ +/* + * Copyright 2010-2023 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 + * + * https://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.scan.filter.customfilter; import org.springframework.core.type.classreading.MetadataReader; diff --git a/src/test/java/org/mybatis/spring/scan/filter/customfilter/ExcludeMaker.java b/src/test/java/org/mybatis/spring/scan/filter/customfilter/ExcludeMaker.java index b4d871e7da..307f654930 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/customfilter/ExcludeMaker.java +++ b/src/test/java/org/mybatis/spring/scan/filter/customfilter/ExcludeMaker.java @@ -1,3 +1,18 @@ +/* + * Copyright 2010-2023 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 + * + * https://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.scan.filter.customfilter; diff --git a/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AnnoExcludeMapper.java b/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AnnoExcludeMapper.java index 64cc3ba15c..a0349afaac 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AnnoExcludeMapper.java +++ b/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AnnoExcludeMapper.java @@ -1,3 +1,18 @@ +/* + * Copyright 2010-2023 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 + * + * https://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.scan.filter.datasource.commonsource; import org.mybatis.spring.scan.filter.customfilter.AnnoTypeFilter; diff --git a/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AssignableMapper.java b/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AssignableMapper.java index cc2cc05870..86e7048815 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AssignableMapper.java +++ b/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AssignableMapper.java @@ -1,3 +1,18 @@ +/* + * Copyright 2010-2023 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 + * + * https://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.scan.filter.datasource.commonsource; import org.mybatis.spring.scan.filter.customfilter.ExcludeMaker; diff --git a/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/CommonDataSourceMapper.java b/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/CommonDataSourceMapper.java index c132943f38..9eda4f5991 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/CommonDataSourceMapper.java +++ b/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/CommonDataSourceMapper.java @@ -1,3 +1,18 @@ +/* + * Copyright 2010-2023 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 + * + * https://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.scan.filter.datasource.commonsource; diff --git a/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource1/DataSource1Mapper.java b/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource1/DataSource1Mapper.java index b89298dba5..733bc9e51c 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource1/DataSource1Mapper.java +++ b/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource1/DataSource1Mapper.java @@ -1,3 +1,18 @@ +/* + * Copyright 2010-2023 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 + * + * https://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.scan.filter.datasource.datasource1; public interface DataSource1Mapper { diff --git a/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource2/DataSource2Mapper.java b/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource2/DataSource2Mapper.java index 6a18893bfa..b1427d2d23 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource2/DataSource2Mapper.java +++ b/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource2/DataSource2Mapper.java @@ -1,3 +1,18 @@ +/* + * Copyright 2010-2023 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 + * + * https://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.scan.filter.datasource.datasource2; public interface DataSource2Mapper { From 789a8e32331358fcfbcfe2195f8b3367f800751f Mon Sep 17 00:00:00 2001 From: lixiaopeng Date: Tue, 11 Jul 2023 18:57:40 +0800 Subject: [PATCH 04/13] replace start import and format code --- .../mybatis/spring/annotation/MapperScannerRegistrar.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java b/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java index a7f194c6a6..446ca568f9 100644 --- a/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java +++ b/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java @@ -37,7 +37,11 @@ import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.AnnotationMetadata; -import org.springframework.core.type.filter.*; +import org.springframework.core.type.filter.AnnotationTypeFilter; +import org.springframework.core.type.filter.AspectJTypeFilter; +import org.springframework.core.type.filter.AssignableTypeFilter; +import org.springframework.core.type.filter.RegexPatternTypeFilter; +import org.springframework.core.type.filter.TypeFilter; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; @@ -59,6 +63,7 @@ public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware { private ResourceLoader resourceLoader; + /** * {@inheritDoc} */ From eb9e79e9af759f9d3e0e35cbc9dfb7ea60314f59 Mon Sep 17 00:00:00 2001 From: lixiaopeng Date: Wed, 12 Jul 2023 13:17:37 +0800 Subject: [PATCH 05/13] move package 'filter' from org.mybatis.spring.scan to org.mybatis.spring --- .../{scan => }/filter/ScanFilterTest.java | 4 ++-- .../{scan => }/filter/config/AppConfig.java | 20 +++++++++---------- .../filter/customfilter/AnnoTypeFilter.java | 2 +- .../filter/customfilter/CustomTypeFilter.java | 2 +- .../filter/customfilter/ExcludeMaker.java | 2 +- .../commonsource/AnnoExcludeMapper.java | 4 ++-- .../commonsource/AssignableMapper.java | 4 ++-- .../commonsource/CommonDataSourceMapper.java | 2 +- .../datasource1/DataSource1Mapper.java | 2 +- .../datasource2/DataSource2Mapper.java | 2 +- 10 files changed, 22 insertions(+), 22 deletions(-) rename src/test/java/org/mybatis/spring/{scan => }/filter/ScanFilterTest.java (97%) rename src/test/java/org/mybatis/spring/{scan => }/filter/config/AppConfig.java (68%) rename src/test/java/org/mybatis/spring/{scan => }/filter/customfilter/AnnoTypeFilter.java (93%) rename src/test/java/org/mybatis/spring/{scan => }/filter/customfilter/CustomTypeFilter.java (95%) rename src/test/java/org/mybatis/spring/{scan => }/filter/customfilter/ExcludeMaker.java (92%) rename src/test/java/org/mybatis/spring/{scan => }/filter/datasource/commonsource/AnnoExcludeMapper.java (83%) rename src/test/java/org/mybatis/spring/{scan => }/filter/datasource/commonsource/AssignableMapper.java (84%) rename src/test/java/org/mybatis/spring/{scan => }/filter/datasource/commonsource/CommonDataSourceMapper.java (91%) rename src/test/java/org/mybatis/spring/{scan => }/filter/datasource/datasource1/DataSource1Mapper.java (91%) rename src/test/java/org/mybatis/spring/{scan => }/filter/datasource/datasource2/DataSource2Mapper.java (91%) diff --git a/src/test/java/org/mybatis/spring/scan/filter/ScanFilterTest.java b/src/test/java/org/mybatis/spring/filter/ScanFilterTest.java similarity index 97% rename from src/test/java/org/mybatis/spring/scan/filter/ScanFilterTest.java rename to src/test/java/org/mybatis/spring/filter/ScanFilterTest.java index 9f8cba64d7..249c25c68f 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/ScanFilterTest.java +++ b/src/test/java/org/mybatis/spring/filter/ScanFilterTest.java @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.mybatis.spring.scan.filter; +package org.mybatis.spring.filter; import com.mockrunner.mock.jdbc.MockDataSource; import org.junit.jupiter.api.Test; import org.mybatis.spring.SqlSessionFactoryBean; -import org.mybatis.spring.scan.filter.config.AppConfig; +import org.mybatis.spring.filter.config.AppConfig; import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.context.annotation.AnnotationConfigApplicationContext; diff --git a/src/test/java/org/mybatis/spring/scan/filter/config/AppConfig.java b/src/test/java/org/mybatis/spring/filter/config/AppConfig.java similarity index 68% rename from src/test/java/org/mybatis/spring/scan/filter/config/AppConfig.java rename to src/test/java/org/mybatis/spring/filter/config/AppConfig.java index 1143bf6684..98548f1596 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/config/AppConfig.java +++ b/src/test/java/org/mybatis/spring/filter/config/AppConfig.java @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.mybatis.spring.scan.filter.config; +package org.mybatis.spring.filter.config; import org.mybatis.spring.annotation.MapperScan; -import org.mybatis.spring.scan.filter.customfilter.AnnoTypeFilter; -import org.mybatis.spring.scan.filter.customfilter.ExcludeMaker; -import org.mybatis.spring.scan.filter.customfilter.CustomTypeFilter; +import org.mybatis.spring.filter.customfilter.ExcludeMaker; +import org.mybatis.spring.filter.customfilter.AnnoTypeFilter; +import org.mybatis.spring.filter.customfilter.CustomTypeFilter; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.FilterType; @@ -26,32 +26,32 @@ public class AppConfig { - @MapperScan(basePackages = "org.mybatis.spring.scan.filter.datasource", + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", excludeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM, classes = CustomTypeFilter.class)}) public static class CustomFilterConfig { } - @MapperScan(basePackages = "org.mybatis.spring.scan.filter.datasource", + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = AnnoTypeFilter.class)}) public static class AnnoFilterConfig { } - @MapperScan(basePackages = "org.mybatis.spring.scan.filter.datasource", + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ExcludeMaker.class)}) public static class AssignableFilterConfig { } - @MapperScan(basePackages = "org.mybatis.spring.scan.filter.datasource", + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", excludeFilters = {@ComponentScan.Filter(type = FilterType.REGEX, - pattern = "org\\.mybatis\\.spring\\.scan\\.filter\\.datasource\\.datasource1\\..*")}) + pattern = "org\\.mybatis\\.spring\\.filter\\.datasource\\.datasource1\\..*")}) public static class RegexFilterConfig { } - @MapperScan(basePackages = "org.mybatis.spring.scan.filter.datasource", + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", excludeFilters = {@ComponentScan.Filter(type = FilterType.ASPECTJ, pattern = "*..DataSource1Mapper")}) public static class AspectJFilterConfig { diff --git a/src/test/java/org/mybatis/spring/scan/filter/customfilter/AnnoTypeFilter.java b/src/test/java/org/mybatis/spring/filter/customfilter/AnnoTypeFilter.java similarity index 93% rename from src/test/java/org/mybatis/spring/scan/filter/customfilter/AnnoTypeFilter.java rename to src/test/java/org/mybatis/spring/filter/customfilter/AnnoTypeFilter.java index d833d5895c..c07e9056e8 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/customfilter/AnnoTypeFilter.java +++ b/src/test/java/org/mybatis/spring/filter/customfilter/AnnoTypeFilter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.mybatis.spring.scan.filter.customfilter; +package org.mybatis.spring.filter.customfilter; import java.lang.annotation.*; diff --git a/src/test/java/org/mybatis/spring/scan/filter/customfilter/CustomTypeFilter.java b/src/test/java/org/mybatis/spring/filter/customfilter/CustomTypeFilter.java similarity index 95% rename from src/test/java/org/mybatis/spring/scan/filter/customfilter/CustomTypeFilter.java rename to src/test/java/org/mybatis/spring/filter/customfilter/CustomTypeFilter.java index 3cdf9e0ab4..4808b677a8 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/customfilter/CustomTypeFilter.java +++ b/src/test/java/org/mybatis/spring/filter/customfilter/CustomTypeFilter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.mybatis.spring.scan.filter.customfilter; +package org.mybatis.spring.filter.customfilter; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; diff --git a/src/test/java/org/mybatis/spring/scan/filter/customfilter/ExcludeMaker.java b/src/test/java/org/mybatis/spring/filter/customfilter/ExcludeMaker.java similarity index 92% rename from src/test/java/org/mybatis/spring/scan/filter/customfilter/ExcludeMaker.java rename to src/test/java/org/mybatis/spring/filter/customfilter/ExcludeMaker.java index 307f654930..1699dd5f62 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/customfilter/ExcludeMaker.java +++ b/src/test/java/org/mybatis/spring/filter/customfilter/ExcludeMaker.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.mybatis.spring.scan.filter.customfilter; +package org.mybatis.spring.filter.customfilter; public interface ExcludeMaker { diff --git a/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AnnoExcludeMapper.java b/src/test/java/org/mybatis/spring/filter/datasource/commonsource/AnnoExcludeMapper.java similarity index 83% rename from src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AnnoExcludeMapper.java rename to src/test/java/org/mybatis/spring/filter/datasource/commonsource/AnnoExcludeMapper.java index a0349afaac..bb6db54c4a 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AnnoExcludeMapper.java +++ b/src/test/java/org/mybatis/spring/filter/datasource/commonsource/AnnoExcludeMapper.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.mybatis.spring.scan.filter.datasource.commonsource; +package org.mybatis.spring.filter.datasource.commonsource; -import org.mybatis.spring.scan.filter.customfilter.AnnoTypeFilter; +import org.mybatis.spring.filter.customfilter.AnnoTypeFilter; @AnnoTypeFilter public interface AnnoExcludeMapper { diff --git a/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AssignableMapper.java b/src/test/java/org/mybatis/spring/filter/datasource/commonsource/AssignableMapper.java similarity index 84% rename from src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AssignableMapper.java rename to src/test/java/org/mybatis/spring/filter/datasource/commonsource/AssignableMapper.java index 86e7048815..7a8398f287 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/AssignableMapper.java +++ b/src/test/java/org/mybatis/spring/filter/datasource/commonsource/AssignableMapper.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.mybatis.spring.scan.filter.datasource.commonsource; +package org.mybatis.spring.filter.datasource.commonsource; -import org.mybatis.spring.scan.filter.customfilter.ExcludeMaker; +import org.mybatis.spring.filter.customfilter.ExcludeMaker; public interface AssignableMapper extends ExcludeMaker { } diff --git a/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/CommonDataSourceMapper.java b/src/test/java/org/mybatis/spring/filter/datasource/commonsource/CommonDataSourceMapper.java similarity index 91% rename from src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/CommonDataSourceMapper.java rename to src/test/java/org/mybatis/spring/filter/datasource/commonsource/CommonDataSourceMapper.java index 9eda4f5991..33cd4bcbb0 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/datasource/commonsource/CommonDataSourceMapper.java +++ b/src/test/java/org/mybatis/spring/filter/datasource/commonsource/CommonDataSourceMapper.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.mybatis.spring.scan.filter.datasource.commonsource; +package org.mybatis.spring.filter.datasource.commonsource; public interface CommonDataSourceMapper { diff --git a/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource1/DataSource1Mapper.java b/src/test/java/org/mybatis/spring/filter/datasource/datasource1/DataSource1Mapper.java similarity index 91% rename from src/test/java/org/mybatis/spring/scan/filter/datasource/datasource1/DataSource1Mapper.java rename to src/test/java/org/mybatis/spring/filter/datasource/datasource1/DataSource1Mapper.java index 733bc9e51c..2249c92e23 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource1/DataSource1Mapper.java +++ b/src/test/java/org/mybatis/spring/filter/datasource/datasource1/DataSource1Mapper.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.mybatis.spring.scan.filter.datasource.datasource1; +package org.mybatis.spring.filter.datasource.datasource1; public interface DataSource1Mapper { } diff --git a/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource2/DataSource2Mapper.java b/src/test/java/org/mybatis/spring/filter/datasource/datasource2/DataSource2Mapper.java similarity index 91% rename from src/test/java/org/mybatis/spring/scan/filter/datasource/datasource2/DataSource2Mapper.java rename to src/test/java/org/mybatis/spring/filter/datasource/datasource2/DataSource2Mapper.java index b1427d2d23..5f94c5b89d 100644 --- a/src/test/java/org/mybatis/spring/scan/filter/datasource/datasource2/DataSource2Mapper.java +++ b/src/test/java/org/mybatis/spring/filter/datasource/datasource2/DataSource2Mapper.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.mybatis.spring.scan.filter.datasource.datasource2; +package org.mybatis.spring.filter.datasource.datasource2; public interface DataSource2Mapper { } From f3344d717239af39a8c2dc546a2a240d49d63f13 Mon Sep 17 00:00:00 2001 From: lixiaopeng Date: Sat, 15 Jul 2023 16:02:43 +0800 Subject: [PATCH 06/13] fix combined exclude filter and add combined filter test --- .../mybatis/spring/annotation/MapperScan.java | 4 +- .../annotation/MapperScannerRegistrar.java | 8 +++- .../mapper/MapperScannerConfigurer.java | 2 + .../mybatis/spring/filter/ScanFilterTest.java | 46 +++++++++++++++++++ .../spring/filter/config/AppConfig.java | 25 ++++++++++ .../datasource1/MapperWithAnnoFilter.java | 22 +++++++++ .../datasource2/DataSource2Mapper1.java | 19 ++++++++ 7 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 src/test/java/org/mybatis/spring/filter/datasource/datasource1/MapperWithAnnoFilter.java create mode 100644 src/test/java/org/mybatis/spring/filter/datasource/datasource2/DataSource2Mapper1.java diff --git a/src/main/java/org/mybatis/spring/annotation/MapperScan.java b/src/main/java/org/mybatis/spring/annotation/MapperScan.java index fee540804f..402dd54058 100644 --- a/src/main/java/org/mybatis/spring/annotation/MapperScan.java +++ b/src/main/java/org/mybatis/spring/annotation/MapperScan.java @@ -196,9 +196,11 @@ * @return a flag that whether execute a property placeholder processing or not */ boolean processPropertyPlaceHolders() default true; - + /** * Specifies which types are not eligible for mapper scanning. + * + * @since 3.0.3 */ ComponentScan.Filter[] excludeFilters() default {}; diff --git a/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java b/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java index 446ca568f9..8603b61c11 100644 --- a/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java +++ b/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java @@ -134,8 +134,12 @@ void registerBeanDefinitions(AnnotationMetadata annoMeta, AnnotationAttributes a } AnnotationAttributes[] excludeFilterArray = annoAttrs.getAnnotationArray("excludeFilters"); - for (AnnotationAttributes excludeFilters : excludeFilterArray) { - builder.addPropertyValue("excludeFilters", typeFiltersFor(excludeFilters)); + if (excludeFilterArray.length > 0) { + List typeFilters = new ArrayList<>(); + for (AnnotationAttributes excludeFilters : excludeFilterArray) { + typeFilters.addAll(typeFiltersFor(excludeFilters)); + } + builder.addPropertyValue("excludeFilters", typeFilters); } String lazyInitialization = annoAttrs.getString("lazyInitialization"); diff --git a/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java b/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java index bfef6ed6b3..8cebdb74c9 100644 --- a/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java +++ b/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java @@ -200,6 +200,8 @@ public void setMarkerInterface(Class superClass) { *

* The scanner will exclude types that define with excludeFilters. * + * @since 3.0.3 + * * @param excludeFilters * list of TypeFilter */ diff --git a/src/test/java/org/mybatis/spring/filter/ScanFilterTest.java b/src/test/java/org/mybatis/spring/filter/ScanFilterTest.java index 249c25c68f..7206fb729e 100644 --- a/src/test/java/org/mybatis/spring/filter/ScanFilterTest.java +++ b/src/test/java/org/mybatis/spring/filter/ScanFilterTest.java @@ -97,6 +97,52 @@ void testAspectJScanFilter() { } + @Test + void combinedScanFilter() { + // combined filter with Custom and Annotation + startContext(AppConfig.CombinedFilterConfig.class); + + // exclude datasource2.DataSource2Mapper by CustomTypeFilter + assertThat(applicationContext.containsBean("dataSource2Mapper")).isEqualTo(false); + // exclude datasource1.MapperWithAnnoFilter by AnnoTypeFilter + assertThat(applicationContext.containsBean("mapperWithAnnoFilter")).isEqualTo(false); + + // other mapper could be registered to beanFactory correctly. + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isEqualTo(true); + assertThat(applicationContext.containsBean("dataSource1Mapper")).isEqualTo(true); + } + + + @Test + void multiPatternRegexScanFilter() { + // multi pattern regex filter + startContext(AppConfig.MultiPatternRegexFilterConfig.class); + + // exclude datasource1 by pattern[0] + assertThat(applicationContext.containsBean("dataSource1Mapper")).isEqualTo(false); + // exclude datasource2 by pattern[1] + assertThat(applicationContext.containsBean("dataSource2Mapper")).isEqualTo(false); + + // other mapper could be registered to beanFactory correctly. + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isEqualTo(true); + } + + @Test + void multiPatternAspectJScanFilter() { + // multi pattern regex filter + startContext(AppConfig.MultiPatternAspectJFilterConfig.class); + + // exclude datasource1 by pattern[0] + assertThat(applicationContext.containsBean("dataSource1Mapper")).isEqualTo(false); + // exclude datasource2 by pattern[1] + assertThat(applicationContext.containsBean("dataSource2Mapper")).isEqualTo(false); + + // other mapper could be registered to beanFactory correctly. + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isEqualTo(true); + assertThat(applicationContext.containsBean("dataSource2Mapper1")).isEqualTo(true); + } + + private void startContext(Class config) { applicationContext = new AnnotationConfigApplicationContext(); // use @MapperScan with excludeFilters in AppConfig.class diff --git a/src/test/java/org/mybatis/spring/filter/config/AppConfig.java b/src/test/java/org/mybatis/spring/filter/config/AppConfig.java index 98548f1596..36e437d07b 100644 --- a/src/test/java/org/mybatis/spring/filter/config/AppConfig.java +++ b/src/test/java/org/mybatis/spring/filter/config/AppConfig.java @@ -57,5 +57,30 @@ public static class RegexFilterConfig { public static class AspectJFilterConfig { } + + + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", + excludeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM, classes = CustomTypeFilter.class), + @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = AnnoTypeFilter.class)}) + public static class CombinedFilterConfig { + + } + + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", + excludeFilters = {@ComponentScan.Filter(type = FilterType.REGEX, + pattern = {"org\\.mybatis\\.spring\\.filter\\.datasource\\.datasource1\\..*", + "org\\.mybatis\\.spring\\.filter\\.datasource\\.datasource2\\..*"})}) + public static class MultiPatternRegexFilterConfig { + + } + + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", + excludeFilters = {@ComponentScan.Filter(type = FilterType.ASPECTJ, + pattern = {"*..DataSource1Mapper", + "*..DataSource2Mapper"})}) + public static class MultiPatternAspectJFilterConfig { + + } + } diff --git a/src/test/java/org/mybatis/spring/filter/datasource/datasource1/MapperWithAnnoFilter.java b/src/test/java/org/mybatis/spring/filter/datasource/datasource1/MapperWithAnnoFilter.java new file mode 100644 index 0000000000..e7b93138e0 --- /dev/null +++ b/src/test/java/org/mybatis/spring/filter/datasource/datasource1/MapperWithAnnoFilter.java @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2023 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 + * + * https://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.filter.datasource.datasource1; + +import org.mybatis.spring.filter.customfilter.AnnoTypeFilter; + +@AnnoTypeFilter +public interface MapperWithAnnoFilter { +} diff --git a/src/test/java/org/mybatis/spring/filter/datasource/datasource2/DataSource2Mapper1.java b/src/test/java/org/mybatis/spring/filter/datasource/datasource2/DataSource2Mapper1.java new file mode 100644 index 0000000000..4df89b6b1f --- /dev/null +++ b/src/test/java/org/mybatis/spring/filter/datasource/datasource2/DataSource2Mapper1.java @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2023 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 + * + * https://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.filter.datasource.datasource2; + +public interface DataSource2Mapper1 { +} From 7fefb72ee38384d4e2a851ee3fcd00a4df27d028 Mon Sep 17 00:00:00 2001 From: lixiaopeng Date: Sat, 15 Jul 2023 17:26:18 +0800 Subject: [PATCH 07/13] modify exception prompt message and add exception test code --- .../annotation/MapperScannerRegistrar.java | 20 ++++++++++-------- .../mybatis/spring/filter/ScanFilterTest.java | 21 +++++++++++++++++++ .../spring/filter/config/AppConfig.java | 18 ++++++++++++++++ 3 files changed, 50 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java b/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java index 8603b61c11..fab9705bfd 100644 --- a/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java +++ b/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java @@ -170,7 +170,7 @@ private List typeFiltersFor(AnnotationAttributes filterAttributes) { switch (filterType) { case ANNOTATION: Assert.isAssignable(Annotation.class, filterClass, - "An error occured when processing a @ComponentScan " + "ANNOTATION type filter: "); + "Specified an unsupported type in 'ANNOTATION' exclude filter of @MapperScan"); @SuppressWarnings("unchecked") Class annoClass = (Class) filterClass; typeFilters.add(new AnnotationTypeFilter(annoClass)); @@ -184,19 +184,21 @@ private List typeFiltersFor(AnnotationAttributes filterAttributes) { typeFilters.add(BeanUtils.instantiateClass(filterClass, TypeFilter.class)); break; default: - throw new IllegalArgumentException("Unknown filter type " + filterType); + throw new IllegalArgumentException("Cannot specify the 'value' or 'classes' attribute if use the " + filterType + " FilterType in exclude filter of @MapperScan"); } } String[] expressionArray = filterAttributes.getStringArray("pattern"); for (String expression : expressionArray) { - String rawName = filterType.toString(); - if ("REGEX".equals(rawName)) { - typeFilters.add(new RegexPatternTypeFilter(Pattern.compile(expression))); - } else if ("ASPECTJ".equals(rawName)) { - typeFilters.add(new AspectJTypeFilter(expression, this.resourceLoader.getClassLoader())); - } else { - throw new IllegalArgumentException("Unknown filter type " + filterType); + switch (filterType) { + case REGEX: + typeFilters.add(new RegexPatternTypeFilter(Pattern.compile(expression))); + break; + case ASPECTJ: + typeFilters.add(new AspectJTypeFilter(expression, this.resourceLoader.getClassLoader())); + break; + default: + throw new IllegalArgumentException("Cannot specify the 'pattern' attribute if use the " + filterType + " FilterType in exclude filter of @MapperScan"); } } return typeFilters; diff --git a/src/test/java/org/mybatis/spring/filter/ScanFilterTest.java b/src/test/java/org/mybatis/spring/filter/ScanFilterTest.java index 7206fb729e..01f257884d 100644 --- a/src/test/java/org/mybatis/spring/filter/ScanFilterTest.java +++ b/src/test/java/org/mybatis/spring/filter/ScanFilterTest.java @@ -23,6 +23,7 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; /** * test the function of excludeFilters in @MapperScan @@ -143,6 +144,26 @@ void multiPatternAspectJScanFilter() { } + @Test + void invalidTypeFilter() { + // invalid value using Annotation type filter + assertThrows(IllegalArgumentException.class, + () -> startContext(AppConfig.InvalidFilterTypeConfig.class)); + } + + @Test + void invalidPropertyPattern() { + assertThrows(IllegalArgumentException.class, + () -> startContext(AppConfig.AnnoTypeWithPatternPropertyConfig.class)); + } + + @Test + void invalidPropertyClasses() { + assertThrows(IllegalArgumentException.class, + () -> startContext(AppConfig.RegexTypeWithClassesPropertyConfig.class)); + } + + private void startContext(Class config) { applicationContext = new AnnotationConfigApplicationContext(); // use @MapperScan with excludeFilters in AppConfig.class diff --git a/src/test/java/org/mybatis/spring/filter/config/AppConfig.java b/src/test/java/org/mybatis/spring/filter/config/AppConfig.java index 36e437d07b..c519520e3a 100644 --- a/src/test/java/org/mybatis/spring/filter/config/AppConfig.java +++ b/src/test/java/org/mybatis/spring/filter/config/AppConfig.java @@ -82,5 +82,23 @@ public static class MultiPatternAspectJFilterConfig { } + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", + excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = ExcludeMaker.class)}) + public static class InvalidFilterTypeConfig { + + } + + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", + excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, + pattern = {"org\\.mybatis\\.spring\\.filter\\.datasource\\.datasource1\\..*"})}) + public static class AnnoTypeWithPatternPropertyConfig { + + } + + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", + excludeFilters = {@ComponentScan.Filter(type = FilterType.REGEX, value = AnnoTypeFilter.class)}) + public static class RegexTypeWithClassesPropertyConfig { + + } } From f449b4c17fdeb22789e5384e4efdc962e5e56a15 Mon Sep 17 00:00:00 2001 From: lixiaopeng Date: Sat, 15 Jul 2023 20:21:52 +0800 Subject: [PATCH 08/13] code format --- .../annotation/MapperScannerRegistrar.java | 11 ++-- .../mapper/MapperScannerConfigurer.java | 2 +- .../spring/filter/config/AppConfig.java | 62 ++++++++----------- .../filter/customfilter/AnnoTypeFilter.java | 2 +- .../filter/customfilter/CustomTypeFilter.java | 4 +- .../filter/customfilter/ExcludeMaker.java | 1 - .../commonsource/CommonDataSourceMapper.java | 1 - 7 files changed, 37 insertions(+), 46 deletions(-) diff --git a/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java b/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java index fab9705bfd..a3c98e603e 100644 --- a/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java +++ b/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java @@ -170,7 +170,7 @@ private List typeFiltersFor(AnnotationAttributes filterAttributes) { switch (filterType) { case ANNOTATION: Assert.isAssignable(Annotation.class, filterClass, - "Specified an unsupported type in 'ANNOTATION' exclude filter of @MapperScan"); + "Specified an unsupported type in 'ANNOTATION' exclude filter of @MapperScan"); @SuppressWarnings("unchecked") Class annoClass = (Class) filterClass; typeFilters.add(new AnnotationTypeFilter(annoClass)); @@ -180,11 +180,12 @@ private List typeFiltersFor(AnnotationAttributes filterAttributes) { break; case CUSTOM: Assert.isAssignable(TypeFilter.class, filterClass, - "An error occured when processing a @ComponentScan " + "CUSTOM type filter: "); + "An error occured when processing a @ComponentScan " + "CUSTOM type filter: "); typeFilters.add(BeanUtils.instantiateClass(filterClass, TypeFilter.class)); break; default: - throw new IllegalArgumentException("Cannot specify the 'value' or 'classes' attribute if use the " + filterType + " FilterType in exclude filter of @MapperScan"); + throw new IllegalArgumentException("Cannot specify the 'value' or 'classes' attribute if use the " + + filterType + " FilterType in exclude filter of @MapperScan"); } } @@ -198,13 +199,13 @@ private List typeFiltersFor(AnnotationAttributes filterAttributes) { typeFilters.add(new AspectJTypeFilter(expression, this.resourceLoader.getClassLoader())); break; default: - throw new IllegalArgumentException("Cannot specify the 'pattern' attribute if use the " + filterType + " FilterType in exclude filter of @MapperScan"); + throw new IllegalArgumentException("Cannot specify the 'pattern' attribute if use the " + filterType + + " FilterType in exclude filter of @MapperScan"); } } return typeFilters; } - private static String generateBaseBeanName(AnnotationMetadata importingClassMetadata, int index) { return importingClassMetadata.getClassName() + "#" + MapperScannerRegistrar.class.getSimpleName() + "#" + index; } diff --git a/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java b/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java index 8cebdb74c9..07455682ad 100644 --- a/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java +++ b/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 the original author or authors. + * Copyright 2010-2023 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. diff --git a/src/test/java/org/mybatis/spring/filter/config/AppConfig.java b/src/test/java/org/mybatis/spring/filter/config/AppConfig.java index c519520e3a..a040e8d359 100644 --- a/src/test/java/org/mybatis/spring/filter/config/AppConfig.java +++ b/src/test/java/org/mybatis/spring/filter/config/AppConfig.java @@ -16,89 +16,81 @@ package org.mybatis.spring.filter.config; import org.mybatis.spring.annotation.MapperScan; -import org.mybatis.spring.filter.customfilter.ExcludeMaker; import org.mybatis.spring.filter.customfilter.AnnoTypeFilter; import org.mybatis.spring.filter.customfilter.CustomTypeFilter; +import org.mybatis.spring.filter.customfilter.ExcludeMaker; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.FilterType; - public class AppConfig { - - @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", - excludeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM, classes = CustomTypeFilter.class)}) + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", excludeFilters = { + @ComponentScan.Filter(type = FilterType.CUSTOM, classes = CustomTypeFilter.class) }) public static class CustomFilterConfig { } - @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", - excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = AnnoTypeFilter.class)}) + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", excludeFilters = { + @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = AnnoTypeFilter.class) }) public static class AnnoFilterConfig { } - @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", - excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ExcludeMaker.class)}) + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", excludeFilters = { + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ExcludeMaker.class) }) public static class AssignableFilterConfig { } - @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", - excludeFilters = {@ComponentScan.Filter(type = FilterType.REGEX, - pattern = "org\\.mybatis\\.spring\\.filter\\.datasource\\.datasource1\\..*")}) + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", excludeFilters = { + @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org\\.mybatis\\.spring\\.filter\\.datasource\\.datasource1\\..*") }) public static class RegexFilterConfig { } - @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", - excludeFilters = {@ComponentScan.Filter(type = FilterType.ASPECTJ, - pattern = "*..DataSource1Mapper")}) + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", excludeFilters = { + @ComponentScan.Filter(type = FilterType.ASPECTJ, pattern = "*..DataSource1Mapper") }) public static class AspectJFilterConfig { } - - @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", - excludeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM, classes = CustomTypeFilter.class), - @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = AnnoTypeFilter.class)}) + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", excludeFilters = { + @ComponentScan.Filter(type = FilterType.CUSTOM, classes = CustomTypeFilter.class), + @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = AnnoTypeFilter.class) }) public static class CombinedFilterConfig { } - @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", - excludeFilters = {@ComponentScan.Filter(type = FilterType.REGEX, - pattern = {"org\\.mybatis\\.spring\\.filter\\.datasource\\.datasource1\\..*", - "org\\.mybatis\\.spring\\.filter\\.datasource\\.datasource2\\..*"})}) + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", excludeFilters = { + @ComponentScan.Filter(type = FilterType.REGEX, pattern = { + "org\\.mybatis\\.spring\\.filter\\.datasource\\.datasource1\\..*", + "org\\.mybatis\\.spring\\.filter\\.datasource\\.datasource2\\..*" }) }) public static class MultiPatternRegexFilterConfig { } - @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", - excludeFilters = {@ComponentScan.Filter(type = FilterType.ASPECTJ, - pattern = {"*..DataSource1Mapper", - "*..DataSource2Mapper"})}) + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", excludeFilters = { + @ComponentScan.Filter(type = FilterType.ASPECTJ, pattern = { "*..DataSource1Mapper", "*..DataSource2Mapper" }) }) public static class MultiPatternAspectJFilterConfig { } - @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", - excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = ExcludeMaker.class)}) + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", excludeFilters = { + @ComponentScan.Filter(type = FilterType.ANNOTATION, value = ExcludeMaker.class) }) public static class InvalidFilterTypeConfig { } - @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", - excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, - pattern = {"org\\.mybatis\\.spring\\.filter\\.datasource\\.datasource1\\..*"})}) + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", excludeFilters = { + @ComponentScan.Filter(type = FilterType.ANNOTATION, pattern = { + "org\\.mybatis\\.spring\\.filter\\.datasource\\.datasource1\\..*" }) }) public static class AnnoTypeWithPatternPropertyConfig { } - @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", - excludeFilters = {@ComponentScan.Filter(type = FilterType.REGEX, value = AnnoTypeFilter.class)}) + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", excludeFilters = { + @ComponentScan.Filter(type = FilterType.REGEX, value = AnnoTypeFilter.class) }) public static class RegexTypeWithClassesPropertyConfig { } } - diff --git a/src/test/java/org/mybatis/spring/filter/customfilter/AnnoTypeFilter.java b/src/test/java/org/mybatis/spring/filter/customfilter/AnnoTypeFilter.java index c07e9056e8..e32715a1c7 100644 --- a/src/test/java/org/mybatis/spring/filter/customfilter/AnnoTypeFilter.java +++ b/src/test/java/org/mybatis/spring/filter/customfilter/AnnoTypeFilter.java @@ -18,7 +18,7 @@ import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) +@Target({ ElementType.TYPE }) @Documented public @interface AnnoTypeFilter { } diff --git a/src/test/java/org/mybatis/spring/filter/customfilter/CustomTypeFilter.java b/src/test/java/org/mybatis/spring/filter/customfilter/CustomTypeFilter.java index 4808b677a8..52f8e05875 100644 --- a/src/test/java/org/mybatis/spring/filter/customfilter/CustomTypeFilter.java +++ b/src/test/java/org/mybatis/spring/filter/customfilter/CustomTypeFilter.java @@ -15,12 +15,12 @@ */ package org.mybatis.spring.filter.customfilter; +import java.io.IOException; + import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.filter.TypeFilter; -import java.io.IOException; - public class CustomTypeFilter implements TypeFilter { @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { diff --git a/src/test/java/org/mybatis/spring/filter/customfilter/ExcludeMaker.java b/src/test/java/org/mybatis/spring/filter/customfilter/ExcludeMaker.java index 1699dd5f62..155235af99 100644 --- a/src/test/java/org/mybatis/spring/filter/customfilter/ExcludeMaker.java +++ b/src/test/java/org/mybatis/spring/filter/customfilter/ExcludeMaker.java @@ -15,6 +15,5 @@ */ package org.mybatis.spring.filter.customfilter; - public interface ExcludeMaker { } diff --git a/src/test/java/org/mybatis/spring/filter/datasource/commonsource/CommonDataSourceMapper.java b/src/test/java/org/mybatis/spring/filter/datasource/commonsource/CommonDataSourceMapper.java index 33cd4bcbb0..1c6446904f 100644 --- a/src/test/java/org/mybatis/spring/filter/datasource/commonsource/CommonDataSourceMapper.java +++ b/src/test/java/org/mybatis/spring/filter/datasource/commonsource/CommonDataSourceMapper.java @@ -15,6 +15,5 @@ */ package org.mybatis.spring.filter.datasource.commonsource; - public interface CommonDataSourceMapper { } From 756531a4f65c1ed3d300abe29e0f04c8b93d1bc3 Mon Sep 17 00:00:00 2001 From: lixiaopeng Date: Sun, 16 Jul 2023 16:51:29 +0800 Subject: [PATCH 09/13] support exclude filter on mapper scan with xml --- .../MapperScannerBeanDefinitionParser.java | 74 ++++++++++ .../mybatis/spring/config/mybatis-spring.xsd | 45 +++++++ .../mybatis/spring/filter/ScanFilterTest.java | 81 +++++------ .../spring/filter/xml/XmlScanFilterTest.java | 126 ++++++++++++++++++ .../filter/xml/appContextAnnoFilter.xml | 45 +++++++ .../filter/xml/appContextAspectJFilter.xml | 45 +++++++ .../filter/xml/appContextAssignFilter.xml | 45 +++++++ .../filter/xml/appContextCombinedFilter.xml | 49 +++++++ .../filter/xml/appContextCustFilter.xml | 45 +++++++ .../filter/xml/appContextInvalidFilter.xml | 45 +++++++ .../filter/xml/appContextInvalidFilter1.xml | 45 +++++++ .../filter/xml/appContextRegexFilter.xml | 45 +++++++ 12 files changed, 646 insertions(+), 44 deletions(-) create mode 100644 src/test/java/org/mybatis/spring/filter/xml/XmlScanFilterTest.java create mode 100644 src/test/java/org/mybatis/spring/filter/xml/appContextAnnoFilter.xml create mode 100644 src/test/java/org/mybatis/spring/filter/xml/appContextAspectJFilter.xml create mode 100644 src/test/java/org/mybatis/spring/filter/xml/appContextAssignFilter.xml create mode 100644 src/test/java/org/mybatis/spring/filter/xml/appContextCombinedFilter.xml create mode 100644 src/test/java/org/mybatis/spring/filter/xml/appContextCustFilter.xml create mode 100644 src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter.xml create mode 100644 src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter1.xml create mode 100644 src/test/java/org/mybatis/spring/filter/xml/appContextRegexFilter.xml diff --git a/src/main/java/org/mybatis/spring/config/MapperScannerBeanDefinitionParser.java b/src/main/java/org/mybatis/spring/config/MapperScannerBeanDefinitionParser.java index 927cd627d6..4a2a1b9aea 100644 --- a/src/main/java/org/mybatis/spring/config/MapperScannerBeanDefinitionParser.java +++ b/src/main/java/org/mybatis/spring/config/MapperScannerBeanDefinitionParser.java @@ -16,6 +16,9 @@ package org.mybatis.spring.config; import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; import org.mybatis.spring.mapper.ClassPathMapperScanner; import org.mybatis.spring.mapper.MapperFactoryBean; @@ -28,9 +31,17 @@ import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.beans.factory.xml.XmlReaderContext; +import org.springframework.core.type.filter.AnnotationTypeFilter; +import org.springframework.core.type.filter.AspectJTypeFilter; +import org.springframework.core.type.filter.AssignableTypeFilter; +import org.springframework.core.type.filter.RegexPatternTypeFilter; +import org.springframework.core.type.filter.TypeFilter; +import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; /** * A {#code BeanDefinitionParser} that handles the element scan of the MyBatis. namespace @@ -57,6 +68,7 @@ public class MapperScannerBeanDefinitionParser extends AbstractBeanDefinitionPar private static final String ATTRIBUTE_LAZY_INITIALIZATION = "lazy-initialization"; private static final String ATTRIBUTE_DEFAULT_SCOPE = "default-scope"; private static final String ATTRIBUTE_PROCESS_PROPERTY_PLACEHOLDERS = "process-property-placeholders"; + private static final String ATTRIBUTE_EXCLUDE_FILTER = "exclude-filter"; /** * {@inheritDoc} @@ -98,6 +110,12 @@ protected AbstractBeanDefinition parseInternal(Element element, ParserContext pa .loadClass(mapperFactoryBeanClassName); builder.addPropertyValue("mapperFactoryBeanClass", mapperFactoryBeanClass); } + + // parse exclude-filter + List typeFilters = parseTypeFilters(element, parserContext, classLoader); + if (!typeFilters.isEmpty()) { + builder.addPropertyValue("excludeFilters", typeFilters); + } } catch (Exception ex) { XmlReaderContext readerContext = parserContext.getReaderContext(); readerContext.error(ex.getMessage(), readerContext.extractSource(element), ex.getCause()); @@ -115,6 +133,62 @@ protected AbstractBeanDefinition parseInternal(Element element, ParserContext pa return builder.getBeanDefinition(); } + private List parseTypeFilters(Element element, ParserContext parserContext, ClassLoader classLoader) { + // Parse exclude filter elements. + List typeFilters = new ArrayList<>(); + NodeList nodeList = element.getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node node = nodeList.item(i); + if (Node.ELEMENT_NODE == node.getNodeType()) { + String localName = parserContext.getDelegate().getLocalName(node); + try { + if (ATTRIBUTE_EXCLUDE_FILTER.equals(localName)) { + TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext); + typeFilters.add(typeFilter); + } + } catch (ClassNotFoundException ex) { + parserContext.getReaderContext().warning("Ignoring non-present type filter class: " + ex, + parserContext.extractSource(element)); + } catch (Exception ex) { + parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause()); + } + } + } + return typeFilters; + } + + @SuppressWarnings("unchecked") + private TypeFilter createTypeFilter(Element element, @Nullable ClassLoader classLoader, ParserContext parserContext) + throws ClassNotFoundException { + String filterType = element.getAttribute("type"); + String expression = element.getAttribute("expression"); + expression = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(expression); + switch (filterType) { + case "annotation": + Class filterAnno = ClassUtils.forName(expression, classLoader); + if(!Annotation.class.isAssignableFrom(filterAnno)){ + throw new IllegalArgumentException( + "Class is not assignable to [" + Annotation.class.getName() + "]: " + expression); + } + return new AnnotationTypeFilter((Class) filterAnno); + case "custom": + Class filterClass = ClassUtils.forName(expression, classLoader); + if (!TypeFilter.class.isAssignableFrom(filterClass)) { + throw new IllegalArgumentException( + "Class is not assignable to [" + TypeFilter.class.getName() + "]: " + expression); + } + return (TypeFilter) BeanUtils.instantiateClass(filterClass); + case "assignable": + return new AssignableTypeFilter(ClassUtils.forName(expression, classLoader)); + case "regex": + return new RegexPatternTypeFilter(Pattern.compile(expression)); + case "aspectj": + return new AspectJTypeFilter(expression, classLoader); + default: + throw new IllegalArgumentException("Unsupported filter type: " + filterType); + } + } + /** * {@inheritDoc} * diff --git a/src/main/resources/org/mybatis/spring/config/mybatis-spring.xsd b/src/main/resources/org/mybatis/spring/config/mybatis-spring.xsd index 5366717e4d..dcf4caae77 100644 --- a/src/main/resources/org/mybatis/spring/config/mybatis-spring.xsd +++ b/src/main/resources/org/mybatis/spring/config/mybatis-spring.xsd @@ -33,6 +33,16 @@ + + + + + + + @@ -160,4 +170,39 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/org/mybatis/spring/filter/ScanFilterTest.java b/src/test/java/org/mybatis/spring/filter/ScanFilterTest.java index 01f257884d..f8f99ae37a 100644 --- a/src/test/java/org/mybatis/spring/filter/ScanFilterTest.java +++ b/src/test/java/org/mybatis/spring/filter/ScanFilterTest.java @@ -15,16 +15,17 @@ */ package org.mybatis.spring.filter; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + import com.mockrunner.mock.jdbc.MockDataSource; + import org.junit.jupiter.api.Test; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.filter.config.AppConfig; import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - /** * test the function of excludeFilters in @MapperScan */ @@ -32,17 +33,17 @@ public class ScanFilterTest { private AnnotationConfigApplicationContext applicationContext; - @Test void testCustomScanFilter() { startContext(AppConfig.CustomFilterConfig.class); - // use org.mybatis.spring.scan.filter.datasource as basePackages and exclude package datasource2 by MapperScan.excludeFilters + // use org.mybatis.spring.scan.filter.datasource as basePackages and exclude package datasource2 by + // MapperScan.excludeFilters // mapper in package datasource2 will not be registered to beanFactory - assertThat(applicationContext.containsBean("dataSource2Mapper")).isEqualTo(false); + assertThat(applicationContext.containsBean("dataSource2Mapper")).isFalse(); // mapper in package datasource except datasource2 will be registered to beanFactory correctly. - assertThat(applicationContext.containsBean("commonDataSourceMapper")).isEqualTo(true); - assertThat(applicationContext.containsBean("dataSource1Mapper")).isEqualTo(true); + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isTrue(); + assertThat(applicationContext.containsBean("dataSource1Mapper")).isTrue(); } @Test @@ -50,26 +51,25 @@ void testAnnoScanFilter() { startContext(AppConfig.AnnoFilterConfig.class); // use @AnnoTypeFilter to exclude mapper - assertThat(applicationContext.containsBean("annoExcludeMapper")).isEqualTo(false); + assertThat(applicationContext.containsBean("annoExcludeMapper")).isFalse(); // mapper in package datasource except datasource2 will be registered to beanFactory correctly. - assertThat(applicationContext.containsBean("commonDataSourceMapper")).isEqualTo(true); - assertThat(applicationContext.containsBean("dataSource1Mapper")).isEqualTo(true); - assertThat(applicationContext.containsBean("dataSource2Mapper")).isEqualTo(true); + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isTrue(); + assertThat(applicationContext.containsBean("dataSource1Mapper")).isTrue(); + assertThat(applicationContext.containsBean("dataSource2Mapper")).isTrue(); } - @Test void testAssignableScanFilter() { startContext(AppConfig.AssignableFilterConfig.class); // exclude AssignableMapper by AssignableFilter - assertThat(applicationContext.containsBean("assignableMapper")).isEqualTo(false); + assertThat(applicationContext.containsBean("assignableMapper")).isFalse(); // mapper in package datasource except datasource2 will be registered to beanFactory correctly. - assertThat(applicationContext.containsBean("commonDataSourceMapper")).isEqualTo(true); - assertThat(applicationContext.containsBean("dataSource1Mapper")).isEqualTo(true); - assertThat(applicationContext.containsBean("dataSource2Mapper")).isEqualTo(true); + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isTrue(); + assertThat(applicationContext.containsBean("dataSource1Mapper")).isTrue(); + assertThat(applicationContext.containsBean("dataSource2Mapper")).isTrue(); } @Test @@ -77,11 +77,11 @@ void testRegexScanFilter() { startContext(AppConfig.RegexFilterConfig.class); // exclude package datasource1 by Regex - assertThat(applicationContext.containsBean("dataSource1Mapper")).isEqualTo(false); + assertThat(applicationContext.containsBean("dataSource1Mapper")).isFalse(); // mapper in package datasource except datasource1 will be registered to beanFactory correctly. - assertThat(applicationContext.containsBean("commonDataSourceMapper")).isEqualTo(true); - assertThat(applicationContext.containsBean("dataSource2Mapper")).isEqualTo(true); + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isTrue(); + assertThat(applicationContext.containsBean("dataSource2Mapper")).isTrue(); } @Test @@ -90,42 +90,40 @@ void testAspectJScanFilter() { startContext(AppConfig.AspectJFilterConfig.class); // exclude dataSource1Mapper by AspectJ - assertThat(applicationContext.containsBean("dataSource1Mapper")).isEqualTo(false); + assertThat(applicationContext.containsBean("dataSource1Mapper")).isFalse(); // mapper in package datasource except datasource1 will be registered to beanFactory correctly. - assertThat(applicationContext.containsBean("commonDataSourceMapper")).isEqualTo(true); - assertThat(applicationContext.containsBean("dataSource2Mapper")).isEqualTo(true); + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isTrue(); + assertThat(applicationContext.containsBean("dataSource2Mapper")).isTrue(); } - @Test void combinedScanFilter() { // combined filter with Custom and Annotation startContext(AppConfig.CombinedFilterConfig.class); // exclude datasource2.DataSource2Mapper by CustomTypeFilter - assertThat(applicationContext.containsBean("dataSource2Mapper")).isEqualTo(false); + assertThat(applicationContext.containsBean("dataSource2Mapper")).isFalse(); // exclude datasource1.MapperWithAnnoFilter by AnnoTypeFilter - assertThat(applicationContext.containsBean("mapperWithAnnoFilter")).isEqualTo(false); + assertThat(applicationContext.containsBean("mapperWithAnnoFilter")).isFalse(); // other mapper could be registered to beanFactory correctly. - assertThat(applicationContext.containsBean("commonDataSourceMapper")).isEqualTo(true); - assertThat(applicationContext.containsBean("dataSource1Mapper")).isEqualTo(true); + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isTrue(); + assertThat(applicationContext.containsBean("dataSource1Mapper")).isTrue(); } - @Test void multiPatternRegexScanFilter() { // multi pattern regex filter startContext(AppConfig.MultiPatternRegexFilterConfig.class); // exclude datasource1 by pattern[0] - assertThat(applicationContext.containsBean("dataSource1Mapper")).isEqualTo(false); + assertThat(applicationContext.containsBean("dataSource1Mapper")).isFalse(); // exclude datasource2 by pattern[1] - assertThat(applicationContext.containsBean("dataSource2Mapper")).isEqualTo(false); + assertThat(applicationContext.containsBean("dataSource2Mapper")).isFalse(); // other mapper could be registered to beanFactory correctly. - assertThat(applicationContext.containsBean("commonDataSourceMapper")).isEqualTo(true); + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isTrue(); } @Test @@ -134,36 +132,32 @@ void multiPatternAspectJScanFilter() { startContext(AppConfig.MultiPatternAspectJFilterConfig.class); // exclude datasource1 by pattern[0] - assertThat(applicationContext.containsBean("dataSource1Mapper")).isEqualTo(false); + assertThat(applicationContext.containsBean("dataSource1Mapper")).isFalse(); // exclude datasource2 by pattern[1] - assertThat(applicationContext.containsBean("dataSource2Mapper")).isEqualTo(false); + assertThat(applicationContext.containsBean("dataSource2Mapper")).isFalse(); // other mapper could be registered to beanFactory correctly. - assertThat(applicationContext.containsBean("commonDataSourceMapper")).isEqualTo(true); - assertThat(applicationContext.containsBean("dataSource2Mapper1")).isEqualTo(true); + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isTrue(); + assertThat(applicationContext.containsBean("dataSource2Mapper1")).isTrue(); } - @Test void invalidTypeFilter() { // invalid value using Annotation type filter - assertThrows(IllegalArgumentException.class, - () -> startContext(AppConfig.InvalidFilterTypeConfig.class)); + assertThrows(IllegalArgumentException.class, () -> startContext(AppConfig.InvalidFilterTypeConfig.class)); } @Test void invalidPropertyPattern() { - assertThrows(IllegalArgumentException.class, - () -> startContext(AppConfig.AnnoTypeWithPatternPropertyConfig.class)); + assertThrows(IllegalArgumentException.class, () -> startContext(AppConfig.AnnoTypeWithPatternPropertyConfig.class)); } @Test void invalidPropertyClasses() { assertThrows(IllegalArgumentException.class, - () -> startContext(AppConfig.RegexTypeWithClassesPropertyConfig.class)); + () -> startContext(AppConfig.RegexTypeWithClassesPropertyConfig.class)); } - private void startContext(Class config) { applicationContext = new AnnotationConfigApplicationContext(); // use @MapperScan with excludeFilters in AppConfig.class @@ -173,7 +167,6 @@ private void startContext(Class config) { applicationContext.start(); } - private void setupSqlSessionFactory(String name) { GenericBeanDefinition definition = new GenericBeanDefinition(); definition.setBeanClass(SqlSessionFactoryBean.class); diff --git a/src/test/java/org/mybatis/spring/filter/xml/XmlScanFilterTest.java b/src/test/java/org/mybatis/spring/filter/xml/XmlScanFilterTest.java new file mode 100644 index 0000000000..9f3228556f --- /dev/null +++ b/src/test/java/org/mybatis/spring/filter/xml/XmlScanFilterTest.java @@ -0,0 +1,126 @@ +/* + * Copyright 2010-2023 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 + * + * https://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.filter.xml; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * test the function of excludeFilters in + */ +public class XmlScanFilterTest { + + private ClassPathXmlApplicationContext applicationContext; + + @Test + void testCustomScanFilter() { + // exclude datasource2 by CustomTypeFilter + startContext("org/mybatis/spring/filter/xml/appContextCustFilter.xml"); + assertThat(applicationContext.containsBean("dataSource2Mapper")).isFalse(); + assertThat(applicationContext.containsBean("mapperWithAnnoFilter")).isTrue(); + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isTrue(); + closeContext(); + } + + @Test + void testAnnoScanFilter() { + // exclude mappers which has @AnnoTypeFilter + startContext("org/mybatis/spring/filter/xml/appContextAnnoFilter.xml"); + assertThat(applicationContext.containsBean("mapperWithAnnoFilter")).isFalse(); + assertThat(applicationContext.containsBean("dataSource1Mapper")).isTrue(); + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isTrue(); + closeContext(); + } + + @Test + void testAssignScanFilter() { + // exclude mappers which can assignable to ExcludeMaker + startContext("org/mybatis/spring/filter/xml/appContextAssignFilter.xml"); + assertThat(applicationContext.containsBean("assignableMapper")).isFalse(); + assertThat(applicationContext.containsBean("dataSource1Mapper")).isTrue(); + assertThat(applicationContext.containsBean("dataSource2Mapper")).isTrue(); + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isTrue(); + closeContext(); + } + + @Test + void testRegexScanFilter() { + // exclude datasource1 by regex + startContext("org/mybatis/spring/filter/xml/appContextRegexFilter.xml"); + assertThat(applicationContext.containsBean("dataSource1Mapper")).isFalse(); + assertThat(applicationContext.containsBean("mapperWithAnnoFilter")).isFalse(); + assertThat(applicationContext.containsBean("dataSource2Mapper")).isTrue(); + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isTrue(); + closeContext(); + } + + @Test + void testAspectJScanFilter() { + // exclude mappers which class name start with DataSource + startContext("org/mybatis/spring/filter/xml/appContextAspectJFilter.xml"); + assertThat(applicationContext.containsBean("dataSource1Mapper")).isFalse(); + assertThat(applicationContext.containsBean("dataSource2Mapper")).isFalse(); + assertThat(applicationContext.containsBean("mapperWithAnnoFilter")).isTrue(); + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isTrue(); + closeContext(); + } + + @Test + void testCombinedScanFilter() { + // exclude filters combined with Annotation Custom and Assignable + startContext("org/mybatis/spring/filter/xml/appContextCombinedFilter.xml"); + assertThat(applicationContext.containsBean("mapperWithAnnoFilter")).isFalse(); + assertThat(applicationContext.containsBean("dataSource2Mapper")).isFalse(); + assertThat(applicationContext.containsBean("assignableMapper")).isFalse(); + assertThat(applicationContext.containsBean("dataSource1Mapper")).isTrue(); + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isTrue(); + closeContext(); + } + + @Test + void invalidPatternFilter() { + try { + startContext("org/mybatis/spring/filter/xml/appContextInvalidFilter.xml"); + } catch (BeanDefinitionParsingException ex) { + assertThat(ex.getMessage()).contains("Class is not assignable to [java.lang.annotation.Annotation]"); + } finally { + closeContext(); + } + } + + @Test + void invalidPropertyPattern() { + assertThrows(BeanDefinitionParsingException.class, + () -> startContext("org/mybatis/spring/filter/xml/appContextInvalidFilter1.xml")); + closeContext(); + } + + + private void startContext(String config) { + applicationContext = new ClassPathXmlApplicationContext(config); + applicationContext.refresh(); + applicationContext.start(); + } + + private void closeContext() { + if (null != applicationContext) + applicationContext.close(); + } +} diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextAnnoFilter.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextAnnoFilter.xml new file mode 100644 index 0000000000..67d1db1e37 --- /dev/null +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextAnnoFilter.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextAspectJFilter.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextAspectJFilter.xml new file mode 100644 index 0000000000..952f381415 --- /dev/null +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextAspectJFilter.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextAssignFilter.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextAssignFilter.xml new file mode 100644 index 0000000000..afddfa1898 --- /dev/null +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextAssignFilter.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextCombinedFilter.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextCombinedFilter.xml new file mode 100644 index 0000000000..60ba0132ec --- /dev/null +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextCombinedFilter.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextCustFilter.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextCustFilter.xml new file mode 100644 index 0000000000..8d5aa2dd72 --- /dev/null +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextCustFilter.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter.xml new file mode 100644 index 0000000000..dd3ee9281d --- /dev/null +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter1.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter1.xml new file mode 100644 index 0000000000..49c126b478 --- /dev/null +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter1.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextRegexFilter.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextRegexFilter.xml new file mode 100644 index 0000000000..6bd23fb252 --- /dev/null +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextRegexFilter.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + From 564c1086fa709d7125418535e4f1b6904ee3ba87 Mon Sep 17 00:00:00 2001 From: lixiaopeng Date: Sun, 16 Jul 2023 17:17:36 +0800 Subject: [PATCH 10/13] add more test --- .../spring/filter/xml/XmlScanFilterTest.java | 11 +++++ .../filter/xml/appContextPlaceHolder.xml | 47 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 src/test/java/org/mybatis/spring/filter/xml/appContextPlaceHolder.xml diff --git a/src/test/java/org/mybatis/spring/filter/xml/XmlScanFilterTest.java b/src/test/java/org/mybatis/spring/filter/xml/XmlScanFilterTest.java index 9f3228556f..ac6af5f929 100644 --- a/src/test/java/org/mybatis/spring/filter/xml/XmlScanFilterTest.java +++ b/src/test/java/org/mybatis/spring/filter/xml/XmlScanFilterTest.java @@ -49,6 +49,17 @@ void testAnnoScanFilter() { closeContext(); } + @Test + void testAnnoScanWithPlaceHolderFilter() { + // exclude mappers which has @AnnoTypeFilter + System.getProperties().put("annoFilter","org.mybatis.spring.filter.customfilter.AnnoTypeFilter"); + startContext("org/mybatis/spring/filter/xml/appContextPlaceHolder.xml"); + assertThat(applicationContext.containsBean("mapperWithAnnoFilter")).isFalse(); + assertThat(applicationContext.containsBean("dataSource1Mapper")).isTrue(); + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isTrue(); + closeContext(); + } + @Test void testAssignScanFilter() { // exclude mappers which can assignable to ExcludeMaker diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextPlaceHolder.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextPlaceHolder.xml new file mode 100644 index 0000000000..75398c62e5 --- /dev/null +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextPlaceHolder.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + From 3e67f256c501a96d894182aeb8c10187185b22d1 Mon Sep 17 00:00:00 2001 From: lixiaopeng Date: Tue, 18 Jul 2023 18:08:52 +0800 Subject: [PATCH 11/13] Optimized process to parse excludeFilters --- .../mybatis/spring/annotation/MapperScan.java | 2 + .../annotation/MapperScannerRegistrar.java | 67 ++++++++++---- .../MapperScannerBeanDefinitionParser.java | 70 +++------------ .../mapper/MapperScannerConfigurer.java | 89 +++++++++++++++++++ .../mybatis/spring/config/mybatis-spring.xsd | 8 +- .../mybatis/spring/filter/ScanFilterTest.java | 57 +++++++++--- .../spring/filter/config/AppConfig.java | 32 ++++++- .../filter/config/application.properties | 18 ++++ .../spring/filter/xml/XmlScanFilterTest.java | 42 ++++++--- .../filter/xml/appContextCombinedFilter.xml | 7 +- .../filter/xml/appContextInvalidFilter2.xml | 45 ++++++++++ .../filter/xml/appContextPlaceHolder1.xml | 49 ++++++++++ .../spring/filter/xml/default.properties | 18 ++++ 13 files changed, 395 insertions(+), 109 deletions(-) create mode 100644 src/test/java/org/mybatis/spring/filter/config/application.properties create mode 100644 src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter2.xml create mode 100644 src/test/java/org/mybatis/spring/filter/xml/appContextPlaceHolder1.xml create mode 100644 src/test/java/org/mybatis/spring/filter/xml/default.properties diff --git a/src/main/java/org/mybatis/spring/annotation/MapperScan.java b/src/main/java/org/mybatis/spring/annotation/MapperScan.java index 402dd54058..e533833492 100644 --- a/src/main/java/org/mybatis/spring/annotation/MapperScan.java +++ b/src/main/java/org/mybatis/spring/annotation/MapperScan.java @@ -201,6 +201,8 @@ * Specifies which types are not eligible for mapper scanning. * * @since 3.0.3 + * + * @return array of customized mapper excludeFilter */ ComponentScan.Filter[] excludeFilters() default {}; diff --git a/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java b/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java index a3c98e603e..88155e15e0 100644 --- a/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java +++ b/src/main/java/org/mybatis/spring/annotation/MapperScannerRegistrar.java @@ -18,8 +18,9 @@ import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; -import java.util.regex.Pattern; +import java.util.Map; import java.util.stream.Collectors; import org.mybatis.spring.mapper.ClassPathMapperScanner; @@ -38,9 +39,7 @@ import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.filter.AnnotationTypeFilter; -import org.springframework.core.type.filter.AspectJTypeFilter; import org.springframework.core.type.filter.AssignableTypeFilter; -import org.springframework.core.type.filter.RegexPatternTypeFilter; import org.springframework.core.type.filter.TypeFilter; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -136,10 +135,17 @@ void registerBeanDefinitions(AnnotationMetadata annoMeta, AnnotationAttributes a AnnotationAttributes[] excludeFilterArray = annoAttrs.getAnnotationArray("excludeFilters"); if (excludeFilterArray.length > 0) { List typeFilters = new ArrayList<>(); + List> rawTypeFilters = new ArrayList<>(); for (AnnotationAttributes excludeFilters : excludeFilterArray) { - typeFilters.addAll(typeFiltersFor(excludeFilters)); + if (excludeFilters.getStringArray("pattern").length > 0) { + // in oder to apply placeholder resolver + rawTypeFilters.addAll(parseFiltersHasPatterns(excludeFilters)); + } else { + typeFilters.addAll(typeFiltersFor(excludeFilters)); + } } builder.addPropertyValue("excludeFilters", typeFilters); + builder.addPropertyValue("rawExcludeFilters", rawTypeFilters); } String lazyInitialization = annoAttrs.getString("lazyInitialization"); @@ -161,6 +167,44 @@ void registerBeanDefinitions(AnnotationMetadata annoMeta, AnnotationAttributes a } + /** + * Parse excludeFilters which FilterType is REGEX or ASPECTJ + * + * @param filterAttributes + * AnnotationAttributes of excludeFilters + * + * @since 3.0.3 + */ + private List> parseFiltersHasPatterns(AnnotationAttributes filterAttributes) { + + List> rawTypeFilters = new ArrayList<>(); + FilterType filterType = filterAttributes.getEnum("type"); + String[] expressionArray = filterAttributes.getStringArray("pattern"); + for (String expression : expressionArray) { + switch (filterType) { + case REGEX: + case ASPECTJ: + Map typeFilter = new HashMap<>(16); + typeFilter.put("type", filterType.name().toLowerCase()); + typeFilter.put("expression", expression); + rawTypeFilters.add(typeFilter); + break; + default: + throw new IllegalArgumentException("Cannot specify the 'pattern' attribute if use the " + filterType + + " FilterType in exclude filter of @MapperScan"); + } + } + return rawTypeFilters; + } + + /** + * Parse excludeFilters which FilterType is ANNOTATION ASSIGNABLE or CUSTOM + * + * @param filterAttributes + * AnnotationAttributes of excludeFilters + * + * @since 3.0.3 + */ private List typeFiltersFor(AnnotationAttributes filterAttributes) { List typeFilters = new ArrayList<>(); @@ -188,21 +232,6 @@ private List typeFiltersFor(AnnotationAttributes filterAttributes) { + filterType + " FilterType in exclude filter of @MapperScan"); } } - - String[] expressionArray = filterAttributes.getStringArray("pattern"); - for (String expression : expressionArray) { - switch (filterType) { - case REGEX: - typeFilters.add(new RegexPatternTypeFilter(Pattern.compile(expression))); - break; - case ASPECTJ: - typeFilters.add(new AspectJTypeFilter(expression, this.resourceLoader.getClassLoader())); - break; - default: - throw new IllegalArgumentException("Cannot specify the 'pattern' attribute if use the " + filterType - + " FilterType in exclude filter of @MapperScan"); - } - } return typeFilters; } diff --git a/src/main/java/org/mybatis/spring/config/MapperScannerBeanDefinitionParser.java b/src/main/java/org/mybatis/spring/config/MapperScannerBeanDefinitionParser.java index 4a2a1b9aea..5858a2e3b6 100644 --- a/src/main/java/org/mybatis/spring/config/MapperScannerBeanDefinitionParser.java +++ b/src/main/java/org/mybatis/spring/config/MapperScannerBeanDefinitionParser.java @@ -17,8 +17,9 @@ import java.lang.annotation.Annotation; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; -import java.util.regex.Pattern; +import java.util.Map; import org.mybatis.spring.mapper.ClassPathMapperScanner; import org.mybatis.spring.mapper.MapperFactoryBean; @@ -31,12 +32,6 @@ import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.beans.factory.xml.XmlReaderContext; -import org.springframework.core.type.filter.AnnotationTypeFilter; -import org.springframework.core.type.filter.AspectJTypeFilter; -import org.springframework.core.type.filter.AssignableTypeFilter; -import org.springframework.core.type.filter.RegexPatternTypeFilter; -import org.springframework.core.type.filter.TypeFilter; -import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import org.w3c.dom.Element; @@ -111,11 +106,12 @@ protected AbstractBeanDefinition parseInternal(Element element, ParserContext pa builder.addPropertyValue("mapperFactoryBeanClass", mapperFactoryBeanClass); } - // parse exclude-filter - List typeFilters = parseTypeFilters(element, parserContext, classLoader); - if (!typeFilters.isEmpty()) { - builder.addPropertyValue("excludeFilters", typeFilters); + // parse raw exclude-filter in + List> rawExcludeFilters = parseScanTypeFilters(element, parserContext); + if (!rawExcludeFilters.isEmpty()) { + builder.addPropertyValue("rawExcludeFilters", rawExcludeFilters); } + } catch (Exception ex) { XmlReaderContext readerContext = parserContext.getReaderContext(); readerContext.error(ex.getMessage(), readerContext.extractSource(element), ex.getCause()); @@ -133,62 +129,24 @@ protected AbstractBeanDefinition parseInternal(Element element, ParserContext pa return builder.getBeanDefinition(); } - private List parseTypeFilters(Element element, ParserContext parserContext, ClassLoader classLoader) { - // Parse exclude filter elements. - List typeFilters = new ArrayList<>(); + private List> parseScanTypeFilters(Element element, ParserContext parserContext) { + List> typeFilters = new ArrayList<>(); NodeList nodeList = element.getChildNodes(); for (int i = 0; i < nodeList.getLength(); i++) { Node node = nodeList.item(i); if (Node.ELEMENT_NODE == node.getNodeType()) { String localName = parserContext.getDelegate().getLocalName(node); - try { - if (ATTRIBUTE_EXCLUDE_FILTER.equals(localName)) { - TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext); - typeFilters.add(typeFilter); - } - } catch (ClassNotFoundException ex) { - parserContext.getReaderContext().warning("Ignoring non-present type filter class: " + ex, - parserContext.extractSource(element)); - } catch (Exception ex) { - parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause()); + if (ATTRIBUTE_EXCLUDE_FILTER.equals(localName)) { + Map filter = new HashMap<>(16); + filter.put("type", ((Element) node).getAttribute("type")); + filter.put("expression", ((Element) node).getAttribute("expression")); + typeFilters.add(filter); } } } return typeFilters; } - @SuppressWarnings("unchecked") - private TypeFilter createTypeFilter(Element element, @Nullable ClassLoader classLoader, ParserContext parserContext) - throws ClassNotFoundException { - String filterType = element.getAttribute("type"); - String expression = element.getAttribute("expression"); - expression = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(expression); - switch (filterType) { - case "annotation": - Class filterAnno = ClassUtils.forName(expression, classLoader); - if(!Annotation.class.isAssignableFrom(filterAnno)){ - throw new IllegalArgumentException( - "Class is not assignable to [" + Annotation.class.getName() + "]: " + expression); - } - return new AnnotationTypeFilter((Class) filterAnno); - case "custom": - Class filterClass = ClassUtils.forName(expression, classLoader); - if (!TypeFilter.class.isAssignableFrom(filterClass)) { - throw new IllegalArgumentException( - "Class is not assignable to [" + TypeFilter.class.getName() + "]: " + expression); - } - return (TypeFilter) BeanUtils.instantiateClass(filterClass); - case "assignable": - return new AssignableTypeFilter(ClassUtils.forName(expression, classLoader)); - case "regex": - return new RegexPatternTypeFilter(Pattern.compile(expression)); - case "aspectj": - return new AspectJTypeFilter(expression, classLoader); - default: - throw new IllegalArgumentException("Unsupported filter type: " + filterType); - } - } - /** * {@inheritDoc} * diff --git a/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java b/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java index 07455682ad..9525f41869 100644 --- a/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java +++ b/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java @@ -18,12 +18,15 @@ import static org.springframework.util.Assert.notNull; import java.lang.annotation.Annotation; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.regex.Pattern; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionTemplate; +import org.springframework.beans.BeanUtils; import org.springframework.beans.PropertyValue; import org.springframework.beans.PropertyValues; import org.springframework.beans.factory.BeanNameAware; @@ -40,7 +43,13 @@ import org.springframework.context.ApplicationContextAware; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.Environment; +import org.springframework.core.type.filter.AnnotationTypeFilter; +import org.springframework.core.type.filter.AspectJTypeFilter; +import org.springframework.core.type.filter.AssignableTypeFilter; +import org.springframework.core.type.filter.RegexPatternTypeFilter; import org.springframework.core.type.filter.TypeFilter; +import org.springframework.lang.Nullable; +import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; /** @@ -113,6 +122,8 @@ public class MapperScannerConfigurer private List excludeFilters; + private List> rawExcludeFilters; + private Class mapperFactoryBeanClass; private ApplicationContext applicationContext; @@ -209,6 +220,20 @@ public void setExcludeFilters(List excludeFilters) { this.excludeFilters = excludeFilters; } + /** + * In order to support process PropertyPlaceHolders. + *

+ * After parsed, it will be added to excludeFilters. + * + * @since 3.0.3 + * + * @param rawExcludeFilters + * list of rawExcludeFilter + */ + public void setRawExcludeFilters(List> rawExcludeFilters) { + this.rawExcludeFilters = rawExcludeFilters; + } + /** * Specifies which {@code SqlSessionTemplate} to use in the case that there is more than one in the spring context. * Usually this is only needed when you have more than one datasource. @@ -432,6 +457,7 @@ private void processPropertyPlaceHolders() { this.sqlSessionTemplateBeanName = getPropertyValue("sqlSessionTemplateBeanName", values); this.lazyInitialization = getPropertyValue("lazyInitialization", values); this.defaultScope = getPropertyValue("defaultScope", values); + this.rawExcludeFilters = getPropertyValueForTypeFilter("rawExcludeFilters", values); } this.basePackage = Optional.ofNullable(this.basePackage).map(getEnvironment()::resolvePlaceholders).orElse(null); this.sqlSessionFactoryBeanName = Optional.ofNullable(this.sqlSessionFactoryBeanName) @@ -441,6 +467,7 @@ private void processPropertyPlaceHolders() { this.lazyInitialization = Optional.ofNullable(this.lazyInitialization).map(getEnvironment()::resolvePlaceholders) .orElse(null); this.defaultScope = Optional.ofNullable(this.defaultScope).map(getEnvironment()::resolvePlaceholders).orElse(null); + this.excludeFilters = mergeExcludeFilters(); } private Environment getEnvironment() { @@ -467,4 +494,66 @@ private String getPropertyValue(String propertyName, PropertyValues values) { } } + @SuppressWarnings("unchecked") + private List> getPropertyValueForTypeFilter(String propertyName, PropertyValues values) { + PropertyValue property = values.getPropertyValue(propertyName); + Object value; + if (property == null || (value = property.getValue()) == null || !(value instanceof List)) { + return null; + } + return (List>) value; + } + + private List mergeExcludeFilters() { + List typeFilters = new ArrayList<>(); + if (this.rawExcludeFilters == null || this.rawExcludeFilters.isEmpty()) { + return this.excludeFilters; + } + if (this.excludeFilters != null && !this.excludeFilters.isEmpty()) { + typeFilters.addAll(this.excludeFilters); + } + try { + for (Map typeFilter : this.rawExcludeFilters) { + typeFilters.add( + createTypeFilter(typeFilter.get("type"), typeFilter.get("expression"), this.getClass().getClassLoader())); + } + } catch (ClassNotFoundException exception) { + throw new RuntimeException("ClassNotFoundException occur when to load the Specified excludeFilter classes.", + exception); + } + return typeFilters; + } + + @SuppressWarnings("unchecked") + private TypeFilter createTypeFilter(String filterType, String expression, @Nullable ClassLoader classLoader) + throws ClassNotFoundException { + + expression = this.getEnvironment().resolvePlaceholders(expression); + + switch (filterType) { + case "annotation": + Class filterAnno = ClassUtils.forName(expression, classLoader); + if (!Annotation.class.isAssignableFrom(filterAnno)) { + throw new IllegalArgumentException( + "Class is not assignable to [" + Annotation.class.getName() + "]: " + expression); + } + return new AnnotationTypeFilter((Class) filterAnno); + case "custom": + Class filterClass = ClassUtils.forName(expression, classLoader); + if (!TypeFilter.class.isAssignableFrom(filterClass)) { + throw new IllegalArgumentException( + "Class is not assignable to [" + TypeFilter.class.getName() + "]: " + expression); + } + return (TypeFilter) BeanUtils.instantiateClass(filterClass); + case "assignable": + return new AssignableTypeFilter(ClassUtils.forName(expression, classLoader)); + case "regex": + return new RegexPatternTypeFilter(Pattern.compile(expression)); + case "aspectj": + return new AspectJTypeFilter(expression, classLoader); + default: + throw new IllegalArgumentException("Unsupported filter type: " + filterType); + } + } + } diff --git a/src/main/resources/org/mybatis/spring/config/mybatis-spring.xsd b/src/main/resources/org/mybatis/spring/config/mybatis-spring.xsd index dcf4caae77..196a6fe35b 100644 --- a/src/main/resources/org/mybatis/spring/config/mybatis-spring.xsd +++ b/src/main/resources/org/mybatis/spring/config/mybatis-spring.xsd @@ -177,10 +177,10 @@ startContext(AppConfig.InvalidFilterTypeConfig.class)); } @Test void invalidPropertyPattern() { + // illegal mixed use type Annotation and pattern assertThrows(IllegalArgumentException.class, () -> startContext(AppConfig.AnnoTypeWithPatternPropertyConfig.class)); } @Test void invalidPropertyClasses() { + // illegal mixed use type REGEX and value assertThrows(IllegalArgumentException.class, () -> startContext(AppConfig.RegexTypeWithClassesPropertyConfig.class)); } diff --git a/src/test/java/org/mybatis/spring/filter/config/AppConfig.java b/src/test/java/org/mybatis/spring/filter/config/AppConfig.java index a040e8d359..aede81c9a2 100644 --- a/src/test/java/org/mybatis/spring/filter/config/AppConfig.java +++ b/src/test/java/org/mybatis/spring/filter/config/AppConfig.java @@ -19,8 +19,11 @@ import org.mybatis.spring.filter.customfilter.AnnoTypeFilter; import org.mybatis.spring.filter.customfilter.CustomTypeFilter; import org.mybatis.spring.filter.customfilter.ExcludeMaker; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.FilterType; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.core.io.ClassPathResource; public class AppConfig { @@ -56,9 +59,16 @@ public static class AspectJFilterConfig { @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", excludeFilters = { @ComponentScan.Filter(type = FilterType.CUSTOM, classes = CustomTypeFilter.class), - @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = AnnoTypeFilter.class) }) + @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = AnnoTypeFilter.class), + @ComponentScan.Filter(type = FilterType.ASPECTJ, pattern = { "*..DataSource1Mapper", + "${exclude-filters.aspectj}" }) }) public static class CombinedFilterConfig { - + @Bean + static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer(); + configurer.setLocation(new ClassPathResource("/org/mybatis/spring/filter/config/application.properties")); + return configurer; + } } @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", excludeFilters = { @@ -93,4 +103,22 @@ public static class AnnoTypeWithPatternPropertyConfig { public static class RegexTypeWithClassesPropertyConfig { } + + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", excludeFilters = { + @ComponentScan.Filter(type = FilterType.REGEX, pattern = "${excludeFilter.regex}") }) + public static class RegexFilterWithPlaceHolderConfig { + + } + + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", excludeFilters = { + @ComponentScan.Filter(type = FilterType.REGEX, pattern = "${exclude-filters.regex}") }) + public static class RegexFilterWithPlaceHolderConfig1 { + @Bean + static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer(); + configurer.setLocation(new ClassPathResource("/org/mybatis/spring/filter/config/application.properties")); + return configurer; + } + + } } diff --git a/src/test/java/org/mybatis/spring/filter/config/application.properties b/src/test/java/org/mybatis/spring/filter/config/application.properties new file mode 100644 index 0000000000..32576e93d0 --- /dev/null +++ b/src/test/java/org/mybatis/spring/filter/config/application.properties @@ -0,0 +1,18 @@ +# +# Copyright 2010-2023 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 +# +# https://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. +# + +exclude-filters.regex=org\.mybatis\.spring\.filter\.datasource\.datasource1\..* +exclude-filters.aspectj=*..CommonDataSourceMapper \ No newline at end of file diff --git a/src/test/java/org/mybatis/spring/filter/xml/XmlScanFilterTest.java b/src/test/java/org/mybatis/spring/filter/xml/XmlScanFilterTest.java index ac6af5f929..59c94c1eca 100644 --- a/src/test/java/org/mybatis/spring/filter/xml/XmlScanFilterTest.java +++ b/src/test/java/org/mybatis/spring/filter/xml/XmlScanFilterTest.java @@ -19,7 +19,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; import org.springframework.context.support.ClassPathXmlApplicationContext; /** @@ -50,9 +49,9 @@ void testAnnoScanFilter() { } @Test - void testAnnoScanWithPlaceHolderFilter() { + void testScanWithPlaceHolderFilter() { // exclude mappers which has @AnnoTypeFilter - System.getProperties().put("annoFilter","org.mybatis.spring.filter.customfilter.AnnoTypeFilter"); + System.getProperties().put("annoFilter", "org.mybatis.spring.filter.customfilter.AnnoTypeFilter"); startContext("org/mybatis/spring/filter/xml/appContextPlaceHolder.xml"); assertThat(applicationContext.containsBean("mapperWithAnnoFilter")).isFalse(); assertThat(applicationContext.containsBean("dataSource1Mapper")).isTrue(); @@ -60,6 +59,18 @@ void testAnnoScanWithPlaceHolderFilter() { closeContext(); } + @Test + void testScanWithPlaceHolderFilter1() { + // exclude datasource2 mappers by CustomTypeFilter + startContext("org/mybatis/spring/filter/xml/appContextPlaceHolder1.xml"); + assertThat(applicationContext.containsBean("dataSource2Mapper")).isFalse(); + assertThat(applicationContext.containsBean("dataSource2Mapper1")).isFalse(); + assertThat(applicationContext.containsBean("mapperWithAnnoFilter")).isTrue(); + assertThat(applicationContext.containsBean("dataSource1Mapper")).isTrue(); + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isTrue(); + closeContext(); + } + @Test void testAssignScanFilter() { // exclude mappers which can assignable to ExcludeMaker @@ -95,34 +106,37 @@ void testAspectJScanFilter() { @Test void testCombinedScanFilter() { - // exclude filters combined with Annotation Custom and Assignable + // exclude filters combined with Annotation Custom Assignable and aspectj expression startContext("org/mybatis/spring/filter/xml/appContextCombinedFilter.xml"); assertThat(applicationContext.containsBean("mapperWithAnnoFilter")).isFalse(); assertThat(applicationContext.containsBean("dataSource2Mapper")).isFalse(); assertThat(applicationContext.containsBean("assignableMapper")).isFalse(); + assertThat(applicationContext.containsBean("commonDataSourceMapper")).isFalse(); + assertThat(applicationContext.containsBean("dataSource1Mapper")).isTrue(); - assertThat(applicationContext.containsBean("commonDataSourceMapper")).isTrue(); closeContext(); } @Test void invalidPatternFilter() { - try { - startContext("org/mybatis/spring/filter/xml/appContextInvalidFilter.xml"); - } catch (BeanDefinitionParsingException ex) { - assertThat(ex.getMessage()).contains("Class is not assignable to [java.lang.annotation.Annotation]"); - } finally { - closeContext(); - } + assertThrows(IllegalArgumentException.class, + () -> startContext("org/mybatis/spring/filter/xml/appContextInvalidFilter.xml")); + closeContext(); } @Test void invalidPropertyPattern() { - assertThrows(BeanDefinitionParsingException.class, - () -> startContext("org/mybatis/spring/filter/xml/appContextInvalidFilter1.xml")); + assertThrows(IllegalArgumentException.class, + () -> startContext("org/mybatis/spring/filter/xml/appContextInvalidFilter1.xml")); closeContext(); } + @Test + void warpedClassNotFoundException() { + assertThrows(RuntimeException.class, + () -> startContext("org/mybatis/spring/filter/xml/appContextInvalidFilter2.xml")); + closeContext(); + } private void startContext(String config) { applicationContext = new ClassPathXmlApplicationContext(config); diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextCombinedFilter.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextCombinedFilter.xml index 60ba0132ec..b882eacb27 100644 --- a/src/test/java/org/mybatis/spring/filter/xml/appContextCombinedFilter.xml +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextCombinedFilter.xml @@ -22,8 +22,9 @@ + http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> @@ -37,6 +38,8 @@ + + @@ -44,6 +47,8 @@ expression="org.mybatis.spring.filter.customfilter.CustomTypeFilter"/> + diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter2.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter2.xml new file mode 100644 index 0000000000..a38d81c527 --- /dev/null +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter2.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextPlaceHolder1.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextPlaceHolder1.xml new file mode 100644 index 0000000000..a4a1e2b951 --- /dev/null +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextPlaceHolder1.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/org/mybatis/spring/filter/xml/default.properties b/src/test/java/org/mybatis/spring/filter/xml/default.properties new file mode 100644 index 0000000000..69057dc48e --- /dev/null +++ b/src/test/java/org/mybatis/spring/filter/xml/default.properties @@ -0,0 +1,18 @@ +# +# Copyright 2010-2023 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 +# +# https://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. +# + +filter.custom=org.mybatis.spring.filter.customfilter.CustomTypeFilter +filter.aspectj=*..CommonDataSourceMapper \ No newline at end of file From 82ef68fa8d646b057a8af5f5ff1a72891d271d40 Mon Sep 17 00:00:00 2001 From: lixiaopeng Date: Wed, 19 Jul 2023 09:38:46 +0800 Subject: [PATCH 12/13] Optimized process to parse excludeFilters and add 'processPropertyPlaceHolders' turn off test --- .../mapper/MapperScannerConfigurer.java | 7 +-- .../mybatis/spring/filter/ScanFilterTest.java | 15 ++++++ .../spring/filter/config/AppConfig.java | 17 +++++++ .../spring/filter/xml/XmlScanFilterTest.java | 10 ++++ .../xml/appContextProcessPlaceHolderOff.xml | 48 +++++++++++++++++++ .../spring/filter/xml/default.properties | 3 +- 6 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 src/test/java/org/mybatis/spring/filter/xml/appContextProcessPlaceHolderOff.xml diff --git a/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java b/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java index 9525f41869..e436513abd 100644 --- a/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java +++ b/src/main/java/org/mybatis/spring/mapper/MapperScannerConfigurer.java @@ -407,7 +407,7 @@ public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { scanner.setAddToConfig(this.addToConfig); scanner.setAnnotationClass(this.annotationClass); scanner.setMarkerInterface(this.markerInterface); - scanner.setExcludeFilters(this.excludeFilters); + scanner.setExcludeFilters(this.excludeFilters = mergeExcludeFilters()); scanner.setSqlSessionFactory(this.sqlSessionFactory); scanner.setSqlSessionTemplate(this.sqlSessionTemplate); scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName); @@ -467,7 +467,6 @@ private void processPropertyPlaceHolders() { this.lazyInitialization = Optional.ofNullable(this.lazyInitialization).map(getEnvironment()::resolvePlaceholders) .orElse(null); this.defaultScope = Optional.ofNullable(this.defaultScope).map(getEnvironment()::resolvePlaceholders).orElse(null); - this.excludeFilters = mergeExcludeFilters(); } private Environment getEnvironment() { @@ -528,7 +527,9 @@ private List mergeExcludeFilters() { private TypeFilter createTypeFilter(String filterType, String expression, @Nullable ClassLoader classLoader) throws ClassNotFoundException { - expression = this.getEnvironment().resolvePlaceholders(expression); + if (this.processPropertyPlaceHolders) { + expression = this.getEnvironment().resolvePlaceholders(expression); + } switch (filterType) { case "annotation": diff --git a/src/test/java/org/mybatis/spring/filter/ScanFilterTest.java b/src/test/java/org/mybatis/spring/filter/ScanFilterTest.java index 14a0e17dd3..76a96a7baf 100644 --- a/src/test/java/org/mybatis/spring/filter/ScanFilterTest.java +++ b/src/test/java/org/mybatis/spring/filter/ScanFilterTest.java @@ -20,6 +20,8 @@ import com.mockrunner.mock.jdbc.MockDataSource; +import java.util.regex.PatternSyntaxException; + import org.junit.jupiter.api.Test; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.filter.config.AppConfig; @@ -189,6 +191,19 @@ void invalidPropertyClasses() { () -> startContext(AppConfig.RegexTypeWithClassesPropertyConfig.class)); } + @Test + void processPropertyPlaceHoldersSwitchTest() { + // if processPropertyPlaceHolders turn off regex compile will fail + assertThrows(PatternSyntaxException.class, + () -> startContext(AppConfig.ProcessPropertyPlaceHoldersOffConfig.class)); + } + + @Test + void processPropertyPlaceHoldersSwitchTest1() { + // processPropertyPlaceHolders turn off has no effect to FilterType which don't use pattern property + startContext(AppConfig.AnnoFilterWithProcessPlaceHolderOffConfig.class); + } + private void startContext(Class config) { applicationContext = new AnnotationConfigApplicationContext(); // use @MapperScan with excludeFilters in AppConfig.class diff --git a/src/test/java/org/mybatis/spring/filter/config/AppConfig.java b/src/test/java/org/mybatis/spring/filter/config/AppConfig.java index aede81c9a2..f331e2d8ce 100644 --- a/src/test/java/org/mybatis/spring/filter/config/AppConfig.java +++ b/src/test/java/org/mybatis/spring/filter/config/AppConfig.java @@ -121,4 +121,21 @@ static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer } } + + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", processPropertyPlaceHolders = false, excludeFilters = { + @ComponentScan.Filter(type = FilterType.REGEX, pattern = "${exclude-filters.regex}") }) + public static class ProcessPropertyPlaceHoldersOffConfig { + @Bean + static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer(); + configurer.setLocation(new ClassPathResource("/org/mybatis/spring/filter/config/application.properties")); + return configurer; + } + } + + @MapperScan(basePackages = "org.mybatis.spring.filter.datasource", processPropertyPlaceHolders = false, excludeFilters = { + @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = AnnoTypeFilter.class) }) + public static class AnnoFilterWithProcessPlaceHolderOffConfig { + + } } diff --git a/src/test/java/org/mybatis/spring/filter/xml/XmlScanFilterTest.java b/src/test/java/org/mybatis/spring/filter/xml/XmlScanFilterTest.java index 59c94c1eca..237e3d1d8d 100644 --- a/src/test/java/org/mybatis/spring/filter/xml/XmlScanFilterTest.java +++ b/src/test/java/org/mybatis/spring/filter/xml/XmlScanFilterTest.java @@ -18,6 +18,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; +import java.util.regex.PatternSyntaxException; + import org.junit.jupiter.api.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; @@ -138,6 +140,14 @@ void warpedClassNotFoundException() { closeContext(); } + @Test + void processPropertyPlaceHoldersSwitchTest() { + // if processPropertyPlaceHolders turn off regex compile will fail + assertThrows(PatternSyntaxException.class, + () -> startContext("org/mybatis/spring/filter/xml/appContextProcessPlaceHolderOff.xml")); + closeContext(); + } + private void startContext(String config) { applicationContext = new ClassPathXmlApplicationContext(config); applicationContext.refresh(); diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextProcessPlaceHolderOff.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextProcessPlaceHolderOff.xml new file mode 100644 index 0000000000..71e28999b0 --- /dev/null +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextProcessPlaceHolderOff.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/org/mybatis/spring/filter/xml/default.properties b/src/test/java/org/mybatis/spring/filter/xml/default.properties index 69057dc48e..9c6582656d 100644 --- a/src/test/java/org/mybatis/spring/filter/xml/default.properties +++ b/src/test/java/org/mybatis/spring/filter/xml/default.properties @@ -15,4 +15,5 @@ # filter.custom=org.mybatis.spring.filter.customfilter.CustomTypeFilter -filter.aspectj=*..CommonDataSourceMapper \ No newline at end of file +filter.aspectj=*..CommonDataSourceMapper +filter.regex=org\.mybatis\.spring\.filter\.datasource\.datasource1\..* \ No newline at end of file From b7f3f35eadded8de98b844d66e3133aef7962830 Mon Sep 17 00:00:00 2001 From: lixiaopeng Date: Wed, 8 May 2024 20:17:43 +0800 Subject: [PATCH 13/13] fix ci fail in windows --- .../org/mybatis/spring/filter/xml/appContextAnnoFilter.xml | 4 ++-- .../org/mybatis/spring/filter/xml/appContextAspectJFilter.xml | 4 ++-- .../org/mybatis/spring/filter/xml/appContextAssignFilter.xml | 4 ++-- .../mybatis/spring/filter/xml/appContextCombinedFilter.xml | 4 ++-- .../org/mybatis/spring/filter/xml/appContextCustFilter.xml | 4 ++-- .../org/mybatis/spring/filter/xml/appContextInvalidFilter.xml | 4 ++-- .../mybatis/spring/filter/xml/appContextInvalidFilter1.xml | 4 ++-- .../mybatis/spring/filter/xml/appContextInvalidFilter2.xml | 4 ++-- .../org/mybatis/spring/filter/xml/appContextPlaceHolder.xml | 4 ++-- .../org/mybatis/spring/filter/xml/appContextPlaceHolder1.xml | 4 ++-- .../spring/filter/xml/appContextProcessPlaceHolderOff.xml | 4 ++-- .../org/mybatis/spring/filter/xml/appContextRegexFilter.xml | 4 ++-- 12 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextAnnoFilter.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextAnnoFilter.xml index 67d1db1e37..c04257fe35 100644 --- a/src/test/java/org/mybatis/spring/filter/xml/appContextAnnoFilter.xml +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextAnnoFilter.xml @@ -27,8 +27,8 @@ - - + + diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextAspectJFilter.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextAspectJFilter.xml index 952f381415..594ba58a3c 100644 --- a/src/test/java/org/mybatis/spring/filter/xml/appContextAspectJFilter.xml +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextAspectJFilter.xml @@ -27,8 +27,8 @@ - - + + diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextAssignFilter.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextAssignFilter.xml index afddfa1898..6336a75ece 100644 --- a/src/test/java/org/mybatis/spring/filter/xml/appContextAssignFilter.xml +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextAssignFilter.xml @@ -27,8 +27,8 @@ - - + + diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextCombinedFilter.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextCombinedFilter.xml index b882eacb27..f477031cc0 100644 --- a/src/test/java/org/mybatis/spring/filter/xml/appContextCombinedFilter.xml +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextCombinedFilter.xml @@ -28,8 +28,8 @@ - - + + diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextCustFilter.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextCustFilter.xml index 8d5aa2dd72..2cc3416793 100644 --- a/src/test/java/org/mybatis/spring/filter/xml/appContextCustFilter.xml +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextCustFilter.xml @@ -27,8 +27,8 @@ - - + + diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter.xml index dd3ee9281d..dfb19ac3d2 100644 --- a/src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter.xml +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter.xml @@ -27,8 +27,8 @@ - - + + diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter1.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter1.xml index 49c126b478..a3c9cb881d 100644 --- a/src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter1.xml +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter1.xml @@ -27,8 +27,8 @@ - - + + diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter2.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter2.xml index a38d81c527..b6f835770f 100644 --- a/src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter2.xml +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextInvalidFilter2.xml @@ -27,8 +27,8 @@ - - + + diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextPlaceHolder.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextPlaceHolder.xml index 75398c62e5..e2f5c502bf 100644 --- a/src/test/java/org/mybatis/spring/filter/xml/appContextPlaceHolder.xml +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextPlaceHolder.xml @@ -28,8 +28,8 @@ - - + + diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextPlaceHolder1.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextPlaceHolder1.xml index a4a1e2b951..2b508e804b 100644 --- a/src/test/java/org/mybatis/spring/filter/xml/appContextPlaceHolder1.xml +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextPlaceHolder1.xml @@ -28,8 +28,8 @@ - - + + diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextProcessPlaceHolderOff.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextProcessPlaceHolderOff.xml index 71e28999b0..f37b79028e 100644 --- a/src/test/java/org/mybatis/spring/filter/xml/appContextProcessPlaceHolderOff.xml +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextProcessPlaceHolderOff.xml @@ -28,8 +28,8 @@ - - + + diff --git a/src/test/java/org/mybatis/spring/filter/xml/appContextRegexFilter.xml b/src/test/java/org/mybatis/spring/filter/xml/appContextRegexFilter.xml index 6bd23fb252..2d909a4fe5 100644 --- a/src/test/java/org/mybatis/spring/filter/xml/appContextRegexFilter.xml +++ b/src/test/java/org/mybatis/spring/filter/xml/appContextRegexFilter.xml @@ -27,8 +27,8 @@ - - + +