@SpringBootApplication和@ComponentScan不能一起使用(bean配置)

时间:2018-07-18 20:57:46

标签: java spring-boot

我有一个多模块项目,但是我的配置有问题。 我在包nl.example.hots.boot

中有一个主要方法
@SpringBootApplication
@EnableAutoConfiguration
@ComponentScan(basePackages = {"nl.*"})
@EntityScan("nl.*")
public class HotsApplication {

    public static void main(String[] args) {
        SpringApplication.run(HotsApplication.class, args);
    }

在nl.example.hots.core。*包中,我有以下课程:

@Service
@AllArgsConstructor
@Transactional(propagation = Propagation.REQUIRED)
public class MapImportService {

    private MapInputModelMapper mapInputModelMapper;
    private MapEntityRepository mapEntityRepository;

    public void add(final MapInputModel mapInputModel) {
        System.out.println(mapInputModel.getName());
        mapEntityRepository.save(mapInputModelMapper.mapToEntiy(mapInputModel));
    }

和:

@Component
@Mapper
public interface MapInputModelMapper {

    MapInputModel mapToInputModel(final MapEntity n);

    MapEntity mapToEntiy(final MapInputModel n);

}

存储库位于软件包nl.example.hots.persistence。*

运行应用程序时出现以下错误:

Description:

Parameter 0 of constructor in nl.example.hots.core.dataimport.MapImportService.MapImportService required a bean of type 'nl.timonschultz.hots.core.map.mapper.MapInputModelMapper' that could not be found.


Action:

Consider defining a bean of type 'nl.example.hots.core.map.mapper.MapInputModelMapper' in your configuration.

当我删除@EnableAutoConfiguration和@ComponentScan批注时,它可以工作。该应用程序启动时没有bean错误。

在这种情况下,我的restcontroller不再起作用:

{
    "timestamp": "2018-07-18T20:48:39.414+0000",
    "status": 404,
    "error": "Not Found",
    "message": "No message available",
    "path": "/maps"
}

当我删除MapImportService类(并且不会弹出Bean错误)时,它可以在相同的URL上工作。

package nl.example.hots.api.data_import;

@RestController
@AllArgsConstructor
public class ImportController {

    private static final String URL = // a url
    private Reader reader;

    @RequestMapping("/maps")
    public String abilityStreamImport() {
        reader.readStream(URL); // calls a class in nl.example.hots.core.*
        return "Greetings from APP!";
    }
}

我尝试了几种不同的组合,并且我有一个不同的项目作为示例,其中注释一起使用,并且可以正常工作。有人可以解释为什么注释一起使用时会产生bean错误吗?为什么仅使用@SpringBootApplication时控制器会给出错误?

在我的Pom.XML中,启动模块对API层具有依赖性,对API层具有依赖性,而对核心层具有依赖性,而对核心层具有依赖性。 我在项目中使用了mapstruct和Lombok。

---编辑:资料库---

@Entity(name = "MAPS")
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
public class MapEntity extends HasId<Long> {

    private String name;

    @ElementCollection
    private List<String> translations;

}

@Repository
public interface MapEntityRepository extends JpaRepository<MapEntity, Long> {
}

@MappedSuperclass
public abstract class HasId<T> {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Setter
    @Getter
    private T id;
}

项目结构:

hots-application;
- hots-api
    - pom.xml
    - nl.example.hots.api.dataimport.ImportController;
- hots-boot
    - pom.xml
    - nl.example.hots.boot.HotsApplication;
- hots-core
    - pom.xml
    - nl.example.hots.core.dataimport.mapImportService.MapImportService;
    - nl.example.hots.core.map.mapper.MapInputModelMapper
- hots-persistence
    - pom.xml
    - nl.example.hots.persistence.common.HasId;
    - nl.example.hots.persistence.map.MapEntity;
    - nl.example.hots.persistence.map.MapEntityRepository;
pom.xml

4 个答案:

答案 0 :(得分:4)

Spring Boot将扫描所有带@SpringBootApplication注释类所在的软件包的软件包和子软件包。您的类位于nl.example.hots.boot中,仅扫描该软件包。其他类别位于不同的非扫描软件包中。

由于采用了这种包结构,并且没有遵循best practices,因此您基本上失去了许多自动配置功能(Spring Data JPA,ReST等),而您不得不求助于手动启用/配置这些功能。对于JPA,部分地通过添加其他@ComponentScan批注。但是,您还需要添加所有@EntityScan等注释,因为这些注释不再被添加(至少没有使用正确的软件包)。

修复非常简单。将带注释的@EnableJpaRepository类移动到@SpringBootApplication包中(如best practices中所述)。除去nl.example.hots以外的其他注释,只需启动您的应用程序。

答案 1 :(得分:1)

您在@AllArgsConstructor上缺少@Autowired注释,请尝试:

@AllArgsConstructor(onConstructor = @__(@Autowired))

答案 2 :(得分:0)

Spring没有创建MapInputModelMapperBean。我从未使用过MapStruct,但是这让我想起了mybatis。对我来说,您用@Mapper和@Component注释MapInputModelMapperBean似乎很奇怪。春天应该如何创造豆子?您是否正在使用执行这种魔术的某种spring-boot-mapstruct软件包?

我进行了快速搜索,发现了这个https://www.credera.com/blog/technology-solutions/mapping-domain-data-transfer-objects-in-spring-boot-with-mapstruct/,看来您需要这样的东西:

@Mapper(componentModel = "spring")
public interface MapInputModelMapper

我想这会生成带有@Component或类似内容的映射器的实现。

答案 3 :(得分:0)

经过反复试验,我设法使它在很大程度上发挥了作用。 我将scanBasePackages =“ nl”添加到SpringBootApplication批注中。

Mapstruct确实给我带来了一些麻烦,但是当我删除它并自己制作一个快速的映射器时,一切都很好。 感谢您提供的所有帮助,建议和链接,以继续阅读!在下一个项目中,我将牢记(最佳实践)建议。 下面是我现在的主要课程

package nl.example.hots.boot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication(scanBasePackages = "nl")
@EntityScan("nl.*")
@EnableJpaRepositories("nl.*")
public class HotsApplication {

    public static void main(String[] args) {
        SpringApplication.run(HotsApplication.class, args);
    }
}