Spring Boot:从库项目中自动装配bean

mar*_*ret 14 multi-module spring-data-jpa spring-ioc spring-boot component-scan

我正在努力从我的自定义库中自动装配bean,并使用gradle导入.在阅读了几个类似的主题后,我仍然无法找到解决方案.

我有Spring Boot项目,它依赖于其他项目(我的自定义库包含Components,Repositories等...).该库是一个Spring不可运行的jar,主要由域实体和存储库组成.它没有可运行的Application.class和任何属性......

当我启动应用程序时,我可以看到我的'CustomUserService'bean(来自库)正在尝试初始化,但是在其中自动装配的bean无法加载(接口UserRepository)...

错误:

com.myProject.customLibrary.configuration.CustomUserDetailsS​​ervice中构造函数的参数0需要一个无法找到的类型为"com.myProject.customLibrary.configuration.UserRepository"的bean.

我甚至试图设置'Order',显式加载它(使用'scanBasePackageClasses'),使用包和标记类扫描,添加额外的'EnableJPARepository'注释但没有任何效果......

代码示例(为简单起见,包名称已更改)

package runnableProject.application;

import runnableProject.application.configuration.ServerConfigurationReference.class
import com.myProject.customLibrary.SharedReference.class

//@SpringBootApplication(scanBasePackages = {"com.myProject.customLibrary", "runnableProject.configuration"}) 
//@EnableJpaRepositories("com.myProject.customLibrary")  

@SpringBootApplication(scanBasePackageClasses = {SharedReference.class, ServerConfigurationReference.class})   
public class MyApplication {

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

}
Run Code Online (Sandbox Code Playgroud)

来自图书馆的课程:

package com.myProject.customLibrary.configuration;

import com.myProject.customLibrary.configuration.UserRepository.class;

@Service
public class CustomUserDetailsService implements UserDetailsService {
    private UserRepository userRepository;    

    @Autowired
    public CustomUserDetailsService(UserRepository userRepository) {
        this.userRepository = userRepository;       
    }
...

package myProject.customLibrary.configuration;

@Repository
public interface UserRepository extends CustomRepository<User> {
    User findByLoginAndStatus(String var1, Status var2);

    ...
}
Run Code Online (Sandbox Code Playgroud)

mar*_*ret 37

刚刚找到解决方案.我没有定义要从单独的库中扫描的基础包,而是在这个库中创建配置类,并使用一大堆注释并将其导入我的主MyApplication.class:

package runnableProject.application;    

import com.myProject.customLibrary.configuration.SharedConfigurationReference.class

@SpringBootApplication
@Import(SharedConfigurationReference.class)
public class MyApplication {

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

}
Run Code Online (Sandbox Code Playgroud)
package com.myProject.customLibrary.configuration;

@Configuration
@ComponentScan("com.myProject.customLibrary.configuration")
@EnableJpaRepositories("com.myProject.customLibrary.configuration.repository")
@EntityScan("com.myProject.customLibrary.configuration.domain")
public class SharedConfigurationReference {}
Run Code Online (Sandbox Code Playgroud)

  • +1但是,如果您想避免导入配置类。您可以在库的“resources”文件夹中创建一个名为“META-INF”的文件夹,并添加一个名为“spring.factories”的文件,其内容为“org.springframework.boot.autoconfigure.EnableAutoConfiguration=&lt;fully_qualified_name_of_configuration_file&gt;”。这将自动配置您的库。 (9认同)
  • 我认为您应该在导入结束时删除“.class”部分 (5认同)
  • 非常简单和干净的答案 (2认同)

PeM*_*eMa 15

您可以在库的“resources”文件夹中创建一个名为“META-INF”的文件夹,并添加一个名为“spring.factories”的文件,其内容为org.springframework.boot.autoconfigure.EnableAutoConfiguration=<fully_qualified_name_of_configuration_file>。这将自动配置您的库。


小智 11

这是针对Spring boot 3更新的答案,并归结为另一个项目中“简单方法”中自动装配库 bean 的要点,其中库声明它们,而另一个项目不必知道它必须导入的内容或指定以便使用它们(一旦库首先是依赖项)。

\n

首先,确保您的库包含.imports资源文件夹中的文件。这意味着,例如,如果您使用 Maven,那么您的 pom 文件<build>部分<resources>将包含如下资源:

\n
<resource>\n    <directory>src/main/resources</directory>\n    <filtering>true</filtering>\n    <includes>\n        \xe2\x80\xa6\n        <include>**/*.imports</include>\n    </includes>\n</resource>\n
Run Code Online (Sandbox Code Playgroud)\n

这很重要,因为 Spring 不再支持该文件(您之前.factories可能已经使用过该文件),但您应该仅使用您的自动配置类作为其内容(如果您有多个自动配置类,则每行一个) :includesrc/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

\n
com.your.library.AutoConfigure\n
Run Code Online (Sandbox Code Playgroud)\n

(如果您的资源文件夹不在,src/main/resources则将其替换为本答案中提到的资源文件夹的路径。)

\n

从这里开始,两个注释对于自动配置类来说似乎是必不可少的。一,@AutoConfiguration这是新的自动配置导入系统的一部分。(这会替换@Configuration导入文件中指定的自动配置类。引入的其他配置类应继续使用@Configuration导入文件中指定的自动配置类。根据这些文档,

\n

两个,@ComponentScan,将告诉它从所有那些 Spring 类(@Component, @Service, @Controller, @Repository, @Bean)中创建可自动装配的 bean ,这些类在@SpringBootApplication. 该注释可以进一步自定义,但是如果您将裸注释放在库顶级包中的类上,它应该只找到该包中的所有 bean(即整个库)。

\n
package com.your.library;\n\nimport org.springframework.boot.autoconfigure.AutoConfiguration;\nimport org.springframework.context.annotation.ComponentScan;\n\n@AutoConfiguration\n@ComponentScan\npublic class AutoConfigure {\n    // intentionally left empty\n}\n
Run Code Online (Sandbox Code Playgroud)\n

恭喜!有了这三个文件(项目文件和其他两个文件中的设置),您的库的 beans 现在应该能够@Autowired使用该库的服务中,而无需服务将其视为任何其他文件与本地的班级不同。

\n

可能会发现自动配置类上需要其他注释或有其他帮助 \xe2\x80\x93 例如,专门配置存储库;或者,如果您AutoConfigurecom.your.library.configuration包中包含该类,那么它可以指定基本包@ComponentScan("com.your.library")以获取configuration包外的 bean。这个答案并不是要详尽地介绍不同的 Spring 注释的作用以及可能与问题的代码示例相关的所有注释;相反,它关注的是问题正在寻找的“缺失的部分”:如何从依赖于该库的另一个项目中的库自动装配这些 bean。(如果您搜索如何在 Spring Boot 中自动装配库 bean/组件,而不是任何更通用或基本的版本,就会出现这个问题。)

\n

从我的测试来看,这些似乎是正常工作的最低限度的部分@Autowired

\n


cha*_*sad 6

接受的答案太麻烦了。您需要做的是在库 jar 中实现您自己的自定义自动配置,以便在主应用程序的类路径扫描中拾取它。更多详情请点击此处