为了让项目结构更清晰在抽取部分通用配置的时候,遇到了一个问题就是@MapperScan的basePackages属性无法通过spring占位符动态配置,于是查看了一下MapperScan注解的属性加载方式,然后得到了解决方案
方案:
1.重新定义自己的MapperScan注解,内容都一样只是@Import的类改为自己写的
2.编写自己的MapperScannerRegistrar,主要区别在于图中这块代码的解析方式改为支持spring占位符的方式解析
3.之后用自己的MapperScan注解去进行spring占位符的方式配置
源码贴一下:
MapperScan.java
/** * @Description 自定义MapperScan实现属性能用spring占位符 * @Author Peihan.Zhang * @CreateTime 2019/11/4 * @Version 0.0.1 * @Email zhangpeihan@jchzbj.com * @param */ package com.alicyu.config; import java.lang.annotation.Annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.mybatis.spring.mapper.MapperFactoryBean; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.context.annotation.Import; import tk.mybatis.spring.annotation.MapperScannerRegistrar; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) @Documented @Import({MyMapperScannerRegistrar.class}) public @interface MapperScan { String[] value() default {}; String[] basePackages() default {}; Class<?>[] basePackageClasses() default {}; Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class; Class<? extends Annotation> annotationClass() default Annotation.class; Class<?> markerInterface() default Class.class; String sqlSessionTemplateRef() default ""; String sqlSessionFactoryRef() default ""; Class<? extends MapperFactoryBean> factoryBean() default MapperFactoryBean.class; }
MyMapperScannerRegistrar.java
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.alicyu.config; import java.lang.annotation.Annotation; import java.util.ArrayList; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.context.EnvironmentAware; import org.springframework.context.ResourceLoaderAware; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.env.Environment; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.AnnotationMetadata; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import tk.mybatis.spring.mapper.ClassPathMapperScanner; import tk.mybatis.spring.mapper.MapperFactoryBean; public class MyMapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware { private ResourceLoader resourceLoader; private Environment environment; public MyMapperScannerRegistrar() { } @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName())); ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); scanner.setMapperProperties(this.environment); if(this.resourceLoader != null) { scanner.setResourceLoader(this.resourceLoader); } Class annotationClass = annoAttrs.getClass("annotationClass"); if(!Annotation.class.equals(annotationClass)) { scanner.setAnnotationClass(annotationClass); } Class markerInterface = annoAttrs.getClass("markerInterface"); if(!Class.class.equals(markerInterface)) { scanner.setMarkerInterface(markerInterface); } Class generatorClass = annoAttrs.getClass("nameGenerator"); if(!BeanNameGenerator.class.equals(generatorClass)) { scanner.setBeanNameGenerator((BeanNameGenerator)BeanUtils.instantiateClass(generatorClass)); } Class mapperFactoryBeanClass = annoAttrs.getClass("factoryBean"); if(!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) { scanner.setMapperFactoryBean((org.mybatis.spring.mapper.MapperFactoryBean)BeanUtils.instantiateClass(mapperFactoryBeanClass)); } scanner.setSqlSessionTemplateBeanName(annoAttrs.getString("sqlSessionTemplateRef")); scanner.setSqlSessionFactoryBeanName(annoAttrs.getString("sqlSessionFactoryRef")); ArrayList basePackages = new ArrayList(); String[] var10 = annoAttrs.getStringArray("value"); int var11 = var10.length; int var12; String clazz; for(var12 = 0; var12 < var11; ++var12) { clazz = var10[var12]; if(StringUtils.hasText(clazz)) { basePackages.add(parsePlaceHolder(clazz)); } } var10 = annoAttrs.getStringArray("basePackages"); var11 = var10.length; for(var12 = 0; var12 < var11; ++var12) { clazz = var10[var12]; if(StringUtils.hasText(clazz)) { basePackages.add(parsePlaceHolder(clazz)); } } Class[] var14 = annoAttrs.getClassArray("basePackageClasses"); var11 = var14.length; for(var12 = 0; var12 < var11; ++var12) { Class var15 = var14[var12]; basePackages.add(ClassUtils.getPackageName(var15)); } scanner.registerFilters(); scanner.doScan(StringUtils.toStringArray(basePackages)); } private String parsePlaceHolder(String pro) { if (pro != null && pro.contains(PropertySourcesPlaceholderConfigurer.DEFAULT_PLACEHOLDER_PREFIX)) { String value = environment.getProperty(pro.substring(2, pro.length() - 1)); if (null == value) { throw new IllegalArgumentException("property " + pro + " can not find!!!"); } return value; } return pro; } @Override public void setEnvironment(Environment environment) { this.environment = environment; } @Override public void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } }
版权声明:本文为qq_16320025原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。