如何从外部目录的 JAR 文件创建一个 Bean

huangapple go评论69阅读模式
英文:

How to create a bean from a jar in external directory

问题

我有一个基本的Spring应用程序,只是加载一个bean,就是这样。我知道在项目内部,我可以在类中使用注释@Component将其标记为bean,Spring应用程序将找到它并采取相应的措施。

然而,我目前正在尝试将该组件放入一个jar包,即放在外部目录/Users/me/plugin.jar中。我不知道如何让Spring在该jar包中搜索已注释的类,而不是搜索本地包。这种做法是否可行?

我希望能够从jar包中加载bean,而无需将jar包包含在类路径中,而是通过搜索目录中的jar包并根据其中的任何jar包动态创建bean。

我已经使用了Java反射和URLClassLoader来从jar包中动态加载类,但无法弄清楚如何在Spring中实现相同的功能。任何关于如何入门的帮助或指导都将非常感谢。谢谢!

附加信息:
该Spring应用程序的设计目标是,在其运行时,它会扫描指定的目录以查找任何jar包,如果找到jar包,它将从其中的一个类创建一个bean。我无法找到让Spring应用程序搜索指定目录以查找用作组件的jar包的方法。我找到的所有内容都只涉及项目内的类。

英文:

I have a basic spring application that simply loads a bean and thats it. I know that within the project I can use the annotation @Component within a class to mark it as a bean and the spring application will find it and act accordingly.

However, I am currently trying to place the component in a jar i.e. plugin.jar in the external directory /Users/me/plugin.jar. I am at a lost for how to get spring to search within that jar for an annotated class instead of the local package. Is this even possible?

I want to be able to load the bean from the jar without the jar being included in the class-path but rather by searching the directory for the jar and dynamically creating the bean based on whatever Jar is in there.

I have used Java reflection and a URLClassLoader for dynamically loading classes from the jar but cannot figure out how to do the same thing in Spring. Any help or direction on how to get started is greatly appreciated. Thanks!

Additional Info:
The spring application is meant to be designed so that while it is running, it scans a designated directory for any jars, if it finds a jar it creates a bean from one of classes inside. I cannot find out how to get the spring application to search scan a specified directory for jars to use as components. Everything I find simply references classes within the project.

答案1

得分: 1

你可以创建一个配置(Configuration),在其中从外部 jar 包初始化所需的 bean。

@Configuration
public class AppConfig {

    @Bean
    public MyBean myBean() {
        return new YourExternalClassName();
    }

}
英文:

You can create a Configuration where you initiate the required bean from external jar.

 @Configuration
    public class AppConfig {
    
    	@Bean
    	public MyBean myBean() {
    		return new YourExternalClassName();
    	}
    
    }

答案2

得分: 0

使用@ComponentScan注解在配置类上,然后指定你的外部组件所在的包:

@Configuration
@ComponentScan(basePackages={"com.foo.bar"})
public class Config { }

你也可以在外部 JAR 中定义一个元注解:

@Retention(value=RUNTIME)
@Target(value=TYPE)
@ComponentScan(basePackages={"com.foo.bar"})
public @interface EnableExternalFoo { }

然后将其应用到一个配置类:

@Configuration
@EnableExternalFoo
public class Config { }
英文:

Use the @ComponentScan annotation on a configuration class, and specify your external component's package:

@Configuration
@ComponentScan(basePackages={"com.foo.bar"})
public class Config { }

You can also define a meta annotion in your external jar:

@Retention(value=RUNTIME)
@Target(value=TYPE)
@ComponentScan(basePackages={"com.foo.bar"})
public @interface EnableExternalFoo { }

And apply this to a configuration class:

@Configuration
@EnableExternalFoo
public class Config { }

答案3

得分: 0

如果您的 plugin.jar 是一个带有 @Component 注解的 Spring 项目,您只需扫描该包:

@ComponentScan(basePackages = {"com.exp"}, basePackageClasses = DependencyBasePackageClass.class)

//external.jar
package com.exp;

import org.springframework.stereotype.Component;

@Component
public class ExpBean {
}

如果该 bean 只是 external.jar 中的一个类,您可以创建一个工厂或将其作为单例,并将其用作 Bean。

英文:

If your plugin.jar is a Spring project with @Component, you can just scan the package:

@ComponentScan(basePackages = {"com.exp"}, basePackageClasses = DependencyBasePackageClass.class)

//external.jar
package com.exp;

import org.springframework.stereotype.Component;

@Component
public class ExpBean {
}

If the bean is just a class in the external.jar, you can create Factory or Singleton it and use it as a Bean.

答案4

得分: 0

但是,我目前正在尝试将组件放入一个JAR文件,即位于外部目录/Users/me/plugin.jar中的plugin.jar。我不知道如何让Spring在该JAR文件中搜索带有注解的类,而不是在本地包中搜索。这种做法是否可行?

您可以在运行时将该JAR添加到应用程序的类路径中。但问题是,在编译时,您还需要将该JAR作为编译依赖项。
由于您使用的是Spring Boot,这意味着您使用Maven或Gradle作为构建工具。
在这种情况下,您不必使用本地目录来指定外部JAR,否则您的构建将仅在您的计算机上以及您计算机的特定状态下可重现(JAR必须位于指定目录中)。您不希望丧失构建工具的优势。
一种更健壮的方法是采用Maven/Gradle的方式:

  • 将该JAR定义为Maven/Gradle构件
  • 将其推送到您的存储库(如果使用,可以是本地和中央存储库)
  • 在应用程序的pom.xml/build.gradle的依赖项中声明该JAR

然后在您的应用程序中,您可以声明一个Foo类的bean,如下所示:

@Configuration
public class ExternalBeanConfig {

    @Bean
    public Foo foo() {
        return new Foo();
    }

}
英文:

> However, I am currently trying to place the component in a jar i.e.
> plugin.jar in the external directory /Users/me/plugin.jar. I am at a
> lost for how to get spring to search within that jar for an annotated
> class instead of the local package. Is this even possible?

You could add the JAR in the classpath of the application at runtime. But the problem is that at compile time you also need to have the jar as a compilation dependency.
Since you use Spring Boot, it means that you use Maven or Gradle as build tool.
In that case, you don't have to use local directories to specify your external jars otherwise your builds will be reproducible only on your machine and in a very specific state of your machine (the jar has to be in the specified directory). You don't want to defeat the build tool advantages.
A more robust way would be to apply the maven/gradle way :

  • define that jar as a maven/gradle artifact
  • push it to your repo (local and central if you use that)
  • declare the jar in the dependencies of the pom.xml/build.gradle of your application

Then in your application you can declare a bean of the Foo class defining in the JAR such as :

@Configuration
public class ExternalBeanConfig {

        @Bean
        public Foo foo() {
            return new Foo();
        }

}

huangapple
  • 本文由 发表于 2020年5月2日 14:20:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/61555307.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定