如何@Autowire 从外部 jar 创建的 spring bean?

Posted

技术标签:

【中文标题】如何@Autowire 从外部 jar 创建的 spring bean?【英文标题】:How can I @Autowire a spring bean that was created from an external jar? 【发布时间】:2015-06-16 18:07:38 【问题描述】:

我创建了一个模块/jar,并将其用作实用工具。我在那里创建了一个服务,如下所示:

@Service
public class PermissionsService  ... 

...它驻留在此处的包中:com.inin.architect.permissions 在我的主应用程序中,我正在引用/加载这个 jar(即设置为maven POM.xml 文件)像这样:

<dependency>
        <groupId>com.inin.architect</groupId>
        <artifactId>permissions</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

在应用程序中,我想使用该服务,例如:

@Autowired
PermissionsService permissions

在应用程序的 spring 设置中,我有这个:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages =  "com.inin.generator", "com.inin.architect.permissions" )
public class WebConfig extends WebMvcConfigurerAdapter implements ServletContextAware  

但是,当我在 tomcat 下运行我的应用程序时,它抱怨 PermissionsService 没有 bean:“org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type .. 。”

那么,我怎样才能将 bean 从 lib 带入我的应用程序?肯定有办法的。您是否必须将库设置为完整的 Spring MVC 应用程序才能正常工作?即你是否也必须在库中设置@Configuration 和@ComponentScan?

【问题讨论】:

这绝对是可能的。首先要检查的是您的外部 jar 文件是否与其他所有内容一起部署到了 tomcat。有时这取决于您的部署方式,而不是弹簧自动装配。 Spring是否扫描了包含这个bean的包?为什么不提供相关代码和配置? 如果这些是真实姓名,您应该遵循通常的命名约定,即类名以大写开头。 @AshleyFrieze - 好点。我成功地将它作为我的 maven pom 文件中的依赖项拉入,并且应用程序编译,但是我如何确定 util jar 也与应用程序一起部署? @JBNizet - 是的,春天正在扫描它,或者至少我认为它是。 【参考方案1】:

您必须至少扫描包含要注入的类的包。例如,使用 Spring 4 注释:

@Configuration
@ComponentScan("com.package.where.my.class.is")
class Config 
...

XML配置也是同样的原理

【讨论】:

这实际上是我的问题。感谢您的回答(接受这个作为答案)。在我正在拉入库的应用程序中,我必须确保在 @ComponentScan() 中包含库的包。我做得不太对,经过仔细检查,我做对了。再次感谢! 实际上,我在@Configuration 类上添加了@EntityScan@ComponentScan,并使用了所有正确的包名称,但似乎我的外部jar 仍然无法自动装配接口服务实现@Service 类。也许问题来自应该注释接口的外部库本身? 是这个jar所在的包还是jar中class所在的包 @jayantmishra 包,其中类和 bean 位于 jar 中。这个答案仍然对我的 Spring 5 项目有所帮助。 感谢您的解决方案。请问,我将类 Config.java 注释为 @Service 并且它不起作用。你知道为什么它不起作用吗?【参考方案2】:

只是一个注释,但你可以将你的依赖与 spring 解耦。在你的 @Configuration 类中创建

@Bean public PermissionsService  permissionsService()
   return new PermissionsService()

这也将允许它被注入。并不是说您必须删除您的 spring 注释,只是一个使其可能在 spring 之外可用的选项。

【讨论】:

是的,在我弄清楚发生了什么并尝试了更多之后,我注意到我可以创建这样的 bean。 如果您尝试自动装配接口,这将不起作用。【参考方案3】:

好的 - 我遇到了完全相同的问题 - 我想从外部 jar 自动装配 mongo db 存储库接口。

我可以使用 using 自动装配该 jar 中的每个 bean

@SpringBootApplication(scanBasePackages = "com.myrootpackage")

但是 - 自动装配接口总是失败,并显示“找不到 blablabla...”

但接口与我可以导入的 bean 在同一个包中。 事实证明,搜索 mongo db 接口并没有考虑到来自 @SpringBootApplication 的 scanBasePackages!

必须通过显式配置

@EnableMongoRepositories(basePackages = "com.myrootpackage")

或者您可以将主类“向上”移动,这样默认搜索也适用于 mongo 接口。所以我理解了这个问题并找到了解决方案。但是我还是有点不开心,因为我需要配置两次相同的查找路径。老实说,我觉得这很愚蠢。

【讨论】:

谢谢!也为假装客户解决了我的问题。很好的答案。 就我而言,我使用的是 couchbase db。所以它会是@EnableCouchbaseRepositories(basePackages = "com.myrootpackage") @EnableJPARepositories 供那些使用 JPA 的人使用 正是我正在寻找的。我正在使用 mongoreactiverepository 添加 @EnableReactiveMongoRepositories 就可以了【参考方案4】:

我在扫描其他项目依赖项中的其他类时遇到了同样的问题,扫描解决方案取决于您需要扫描的类的类型,如下所示:

如果是普通的@Component,则使用@Service注解

@ComponentScan("com.mypackge1","com.mypackage2")

如果类的类型是基于实体使用的领域对象

@EntityScan("com.mypackge1.domain")

如果 JPA 存储库类

@EnableJpaRepositories(basePackages = "com.mypackage.repository")

如果 Redis 存储库类使用

@EnableRedisRepositories(basePackages = "com.mypackage.repository")

Mongo 等也一样

【讨论】:

【参考方案5】:

您可以通过以下方式在主应用程序中为 com.inin.architect.permissions 导入 application-context.xml。

<import resource="classpath:/permissionApplicationContext.xml" />

这将使您能够从您定义的 com.inin.architect.permissions 自动装配 bean。

【讨论】:

以上是关于如何@Autowire 从外部 jar 创建的 spring bean?的主要内容,如果未能解决你的问题,请参考以下文章

如何将外部jar文件传递给spring boot项目? [复制]

从外部 Jar 加载属性文件

在 IntelliJ IDEA 中将外部库添加到工件 jar

如何在 Android 项目中使用外部 JAR?

如何从外部jar自动运行java任务?

如何为maven项目添加依赖? (如何从外部 jar 文件中找出 GroupID / ArtifactID)[重复]