Spring Boot自定义Starter不使用@EntityScan加载实体可行吗?
Spring Boot自定义Starter实体加载问题
我正在测试Spring Boot自定义Starter,除实体加载外其余配置均已完成。尝试在@AutoConfiguration类中用@Import加载实体但无效;若在Starter中使用@EntityScan,依赖该Starter的项目若自有实体,也必须添加@EntityScan,这违背了Starter自动配置的初衷——引入Starter后应无需额外操作即可使用,仅需按需覆盖配置或声明属性。
Starter自动配置类示例
@AutoConfiguration(after = JpaRepositoriesAutoConfiguration.class) //@AutoConfigureAfter(JpaRepositoriesAutoConfiguration.class) @EnableJpaRepositories(basePackages = "com.example.springbootstarterexample.repository") @Import({SomeServiceImpl.class, SomeEntityController.class /*, SomeEntity.class NOT WORKING*/}) @EntityScan(basePackages = "com.example.springbootstarterexample.domain") public class ExampleAutoConfiguration { }
依赖Starter的消费端配置情况
场景1:Starter中使用@EntityScan时
消费端需添加自身实体扫描配置:
@SpringBootApplication @EntityScan(basePackages = "com.example.springbootconsumer.model") public class SpringBootConsumerApplication { public static void main(String[] args) { SpringApplication.run(SpringBootConsumerApplication.class, args); } }
场景2:移除Starter中的@EntityScan时
消费端必须同时指定自身和Starter的实体包路径:
@SpringBootApplication @EntityScan(basePackages = {"com.example.springbootconsumer.model", "com.example.springbootstarterexample.domain"}) public class SpringBootConsumerApplication { public static void main(String[] args) { SpringApplication.run(SpringBootConsumerApplication.class, args); } }
这完全破坏了自动配置,因为消费端必须知晓Starter中实体的位置才能启动应用。
编辑1:尝试使用@AutoConfigurationPackage
配置类调整如下:
@AutoConfiguration(after = JpaRepositoriesAutoConfiguration.class) //@AutoConfigureAfter(JpaRepositoriesAutoConfiguration.class) //@EnableJpaRepositories(basePackages = {"com.example.springbootstarterexample.repository"}) @AutoConfigurationPackage(basePackageClasses = {SomeEntity.class, SomeEntityRepository.class}) @Import({SomeServiceImpl.class, SomeEntityController.class /*, SomeEntity.class NOT WORKING*/}) //@EntityScan(basePackages = "com.example.springbootstarterexample.domain") public class ExampleAutoConfiguration { }
此时无法实例化Repository,报错:
Description: Parameter 0 of constructor in com.example.springbootstarterexample.service.SomeServiceImpl required a bean of type 'com.example.springbootstarterexample.repository.SomeEntityRepository' that could not be found. Action: Consider defining a bean of type 'com.example.springbootstarterexample.repository.SomeEntityRepository' in your configuration.
若添加@EnableJpaRepositories,可找到Repository但无法识别实体:
@AutoConfiguration(after = JpaRepositoriesAutoConfiguration.class) //@AutoConfigureAfter(JpaRepositoriesAutoConfiguration.class) @EnableJpaRepositories(basePackages = {"com.example.springbootstarterexample.repository"}) @AutoConfigurationPackage(basePackageClasses = {SomeEntity.class}) @Import({SomeServiceImpl.class, SomeEntityController.class /*, SomeEntity.class NOT WORKING*/}) //@EntityScan(basePackages = "com.example.springbootstarterexample.domain") public class ExampleAutoConfiguration { }
错误信息:
Caused by: java.lang.IllegalArgumentException: Not a managed type: class com.example.springbootstarterexample.domain.SomeEntity
使用包名配置也得到相同结果。
编辑2:通过META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports加载配置类
移除@Import,配置类如下:
@AutoConfiguration(after = JpaRepositoriesAutoConfiguration.class) //@AutoConfigureAfter(JpaRepositoriesAutoConfiguration.class) //@EnableJpaRepositories(basePackages = {"com.example.springbootstarterexample.repository"}) @AutoConfigurationPackage(basePackageClasses = {SomeEntity.class, SomeServiceImpl.class, SomeEntityController.class, SomeEntityRepository.class}) //@Import({SomeServiceImpl.class, SomeEntityController.class /*, SomeEntity.class NOT WORKING*/}) //@EntityScan(basePackages = "com.example.springbootstarterexample.domain") public class ExampleAutoConfiguration { }
消费端尝试注入Bean时报错:
Description: Parameter 0 of constructor in com.example.springbootconsumer.SpringBootConsumerApplication required a bean of type 'com.example.springbootstarterexample.service.SomeService' that could not be found. Action: Consider defining a bean of type 'com.example.springbootstarterexample.service.SomeService' in your configuration.
似乎未加载任何配置。
编辑3:调整包结构并开启TRACE日志
将所有类放在ExampleAutoConfiguration所在的同一包下,配置类如下:
@AutoConfiguration(after = JpaRepositoriesAutoConfiguration.class) //@AutoConfigureAfter(JpaRepositoriesAutoConfiguration.class) //@EnableJpaRepositories(basePackages = {"com.example.springbootstarterexample.repository"}) @AutoConfigurationPackage //@Import({SomeServiceImpl.class, SomeEntityController.class /*, SomeEntity.class NOT WORKING*/}) //@EntityScan(basePackages = "com.example.springbootstarterexample.domain") public class ExampleAutoConfiguration { }
日志显示@AutoConfiguration类已被扫描,但未找到包中定义的任何Bean:
2022-09-08 20:03:24.495 TRACE 17132 --- [ main] a.ConfigurationClassBeanDefinitionReader : Registered bean definition for imported class 'com.example.springbootstarterexample.autoconfigure.ExampleAutoConfiguration'
而使用常规配置时,所有Bean都会被创建:
2022-09-08 22:31:34.580 TRACE 2308 --- [ main] a.ConfigurationClassBeanDefinitionReader : Registered bean definition for imported class 'com.example.springbootstarterexample.service.SomeServiceImpl' 2022-09-08 22:31:34.581 TRACE 2308 --- [ main] a.ConfigurationClassBeanDefinitionReader : Registered bean definition for imported class 'com.example.springbootstarterexample.controller.SomeEntityController' 2022-09-08 22:31:34.585 TRACE 2308 --- [ main] a.ConfigurationClassBeanDefinitionReader : Registered bean definition for imported class 'com.example.springbootstarterexample.autoconfigure.ExampleAutoConfiguration' 2022-09-08 22:31:34.685 TRACE 2308 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Spring Data JPA - Registering repository: someEntityRepository - Interface: com.example.springbootstarterexample.repository.SomeEntityRepository - Factory: org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean 2022-09-08 22:31:39.094 DEBUG 2308 --- [ main] org.hibernate.cfg.Ejb3Column : Binding column: Ejb3DiscriminatorColumn{logicalColumnName'DTYPE', discriminatorTypeName='string'} 2022-09-08 22:31:39.112 DEBUG 2308 --- [ main] o.h.cfg.annotations.EntityBinder : Import with entity name SomeEntity 2022-09-08 22:31:39.113 TRACE 2308 --- [ main] o.h.b.i.InFlightMetadataCollectorImpl : Import: SomeEntity -> com.example.springbootstarterexample.domain.SomeEntity 2022-09-08 22:31:39.114 TRACE 2308 --- [ main] o.h.b.i.InFlightMetadataCollectorImpl : Import: com.example.springbootstarterexample.domain.SomeEntity -> com.example.springbootstarterexample.domain.SomeEntity
内容的提问来源于stack exchange,提问作者Pp88
相关产品推荐
相关产品推荐

