如何阻止名为“main”的工具干扰真正的“main” SpringBoot 应用程序?

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

How to stop utility "main" from interfering with real "main" SpringBoot application?

问题

我有一个一直运行正常的SpringBoot应用程序:

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }, 
    scanBasePackageClasses = { IndexSyncController.class, IndexerService.class })
@ImportResource("classpath:/spring.xml")
public class AppLauncher {

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

同时,目前在 src/test/java 目录下,我有一个名为 "utility" 的东西,它有自己的主方法。这也一直运行正常,但只能在我的开发环境中运行:

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class,
    WebMvcAutoConfiguration.class })
public class AuditApp {

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

    @Bean
    public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
        return args -> {
            // ...
        };
    }
}

现在我有一个新的需求:

我需要将 src/test/java 中的 AuditApp 工具移植到生产jar包中。

那我只需将它从 src/test/java 移动到 src/main/java,对吗?并不是!我在这样做时遇到的第一个障碍是,主应用程序会尝试运行 commandLineRunner()。基于过去类似需求的经验,我相信这只是冰山一角,还会有其他问题。

是否有通用的最佳实践或清单,用于如何实现这一点?

英文:

I have a SpringBoot app that has been working fine:

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }, 
	scanBasePackageClasses = { IndexSyncController.class, IndexerService.class })
@ImportResource("classpath:/spring.xml")
public class AppLauncher {

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

And also currently sitting in src/test/java, I have a "utility" which has its own main method. This too has been working fine, but can only launched in my development environment:

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class,
		WebMvcAutoConfiguration.class })
public class AuditApp {

	public static void main(String[] args) {
		SpringApplication.run(AppLauncher.class, args);
	}
	
	@Bean
	public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
		return args -> {
			...
		};
	}

Now I have a new requirement

> I need to take the AuditApp utility from src/test/java and make it available in the production jar.

So I just move it from src/test/java to src/main/java right? Nope! Very first obstacle I ran into when I do that, is that the main application tries to run the commandLineRunner(). Because of past experience with a similar requirement, I believe this is just the tip of the iceberg and there will be additional issues.

Is there a canonical, general best-practice or checklist for how to accomplish this?

答案1

得分: 1

考虑的第一件事是真正导致你问题的原因。
你错过了所提到的类的包,但从你的症状来看,我怀疑你的AuditAppAppLauncher所在的包相同,或者在AppLauncher所在的子包中(或者在由导入的spring.xml内部声明的配置扫描的包中)。

@SpringBootApplication@SpringBootConfiguration@ComponentScan的缩写(除了其他)。
因此,AppLauncher会将AuditApp视为@SpringBootConfiguration进行包扫描,并实例化在此配置中创建的bean。AuditApp.main方法从未被调用,但在配置中声明的bean被实例化。

假设你在com.yourappAppLauncher,而在com.yourapp.auditAuditApp
如果你将实用程序应用移动到不在AppLauncher的包扫描范围内的包中,比如com.yourauditapp。当运行原始应用程序时,CommandLineRunner bean 将不会被创建。而且AuditApp不会影响原始应用程序。

它可能干扰的另一种方式是引入可能触发一些Spring Boot自动配置的依赖关系。

英文:

The first thing to consider is the real reason of your problem.
You missed out packages of mentioned classes, but looking at your symptoms, I suspect your AuditApp is in the same package, or in a subpackage of one the AppLauncher is in (or is in package scanned by config declared inside imported spring.xml).

The @SpringBootApplication is an abbreviation for (amongst other) @SpringBootConfiguration and @ComponentScan.
Because of this the AppLauncher treats AuditApp as a @SpringBootConfiguration on a package scan and instantiates beans created within this config. The AuditApp.main method is never called, but the beans declared in the config are instantianted.

Let's say you have AppLauncher in com.yourapp and AuditApp in com.yourapp.audit.
If you move your utility application to the package which is not under the package scan for AppLauncher, like com.yourauditapp. The CommandLineRunner bean won't be created when running the original application. And the AuditApp won't affect the original application.

The only other way it can interfere is when it introduces dependencies which may trigger some Spring-Boot autoconfigurations.

huangapple
  • 本文由 发表于 2020年9月8日 00:52:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/63781498.html
匿名

发表评论

匿名网友

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

确定