Решите проблему с большим парнем сегодня. Объект, введенный @Autowired, не соответствует ожиданиям. Результат из-за проблемы со сканированием Mybatis.
@Mapper
Эта аннотация является классом аннотаций, сканируемым по умолчанию при автоматической настройке Mybatis.
MybatisAutoConfiguration.AutoConfiguredMapperScannerRegistrar#registerBeanDefinitions
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
logger.debug("Searching for mappers annotated with @Mapper");
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
try {
if (this.resourceLoader != null) {
scanner.setResourceLoader(this.resourceLoader);
}
List<String> packages = AutoConfigurationPackages.get(this.beanFactory);
if (logger.isDebugEnabled()) {
for (String pkg : packages) {
logger.debug("Using auto-configuration base package '{}'", pkg);
}
}
// 扫描 @Mapper 注解的类
scanner.setAnnotationClass(Mapper.class);
scanner.registerFilters();
scanner.doScan(StringUtils.toStringArray(packages));
} catch (IllegalStateException ex) {
logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.", ex);
}
}
@MapperScan
Установите свойства сканирования, для ручного сканирования вы можете установить пакеты сканирования, примечания к сканированию и другую информацию.
MapperScannerRegistrar#registerBeanDefinitions
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
// this check is needed in Spring 3.1
if (resourceLoader != null) {
scanner.setResourceLoader(resourceLoader);
}
Class<? extends Annotation> 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<? extends BeanNameGenerator> generatorClass = annoAttrs.getClass("nameGenerator");
if (!BeanNameGenerator.class.equals(generatorClass)) {
scanner.setBeanNameGenerator(BeanUtils.instantiateClass(generatorClass));
}
Class<? extends MapperFactoryBean> mapperFactoryBeanClass = annoAttrs.getClass("factoryBean");
if (!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) {
scanner.setMapperFactoryBean(BeanUtils.instantiateClass(mapperFactoryBeanClass));
}
scanner.setSqlSessionTemplateBeanName(annoAttrs.getString("sqlSessionTemplateRef"));
scanner.setSqlSessionFactoryBeanName(annoAttrs.getString("sqlSessionFactoryRef"));
List<String> basePackages = new ArrayList<String>();
for (String pkg : annoAttrs.getStringArray("value")) {
if (StringUtils.hasText(pkg)) {
basePackages.add(pkg);
}
}
for (String pkg : annoAttrs.getStringArray("basePackages")) {
if (StringUtils.hasText(pkg)) {
basePackages.add(pkg);
}
}
for (Class<?> clazz : annoAttrs.getClassArray("basePackageClasses")) {
basePackages.add(ClassUtils.getPackageName(clazz));
}
scanner.registerFilters();
scanner.doScan(StringUtils.toStringArray(basePackages));
}
С помощью приведенного выше кода можно обнаружить, что все пакеты, отсканированные @MapperScan, будут отсканированы (вставлены в MapperFactoryBean).
проблема
Если @MapperScan сканирует все по умолчанию, а @SpringBoot сканирует все, является ли объект в нем MapperFactoryBean или реальным объектом?
MapperFactoryBean просканирован на наличие @service
решать
Опять же, это не проблема дизайна людей, а проблема использования
Почему Mybatis внедряет все классы по пути в отсканированном пакете
Если вас попросят спроектировать, как вы узнаете, является ли отсканированный класс тем классом, который MyBatis должен внедрить?
специальное представительство
Этот метод уже поддерживается @mapper, и его не нужно отсканировать. Он загружен по умолчанию. Если вы снова используете @Mapperscan, это действительно ненужно.
Сканировать только пакет картографа
Проблема вот в чем, если дело только в юзере, если не думать об этом, то скорее всего сканируете большой пакет напрямую, потому что лень.
личное предложение
На самом деле, мое личное предложение - делать это автоматически и стараться не делать это вручную.Поскольку автоматический был очень хорошо подготовлен провайдером, проблем не будет, но будут некоторые человеческие упущения или необдуманные или нереализованные проблемы в части ручного управления, в результате чего пользователь умрет, не подозревая об этом.
Так что лично я думаю, что лучший способ - это @Mapper, он будет завершен автоматически.