4

我正在设置一个SpringBoot 应用程序,它应该在命令行上执行。该应用程序包含多个 CommandLineRunner,如果需要的选项通过命令行执行传递,它们会运行它们的特定逻辑。我使用Gradle作为构建工具。

每个跑步者都有一个初始化方法来解析选项并在没有选项通过时打印出帮助语句,我已将其外包给一个方面类。
这就是问题的开始。

起初,我已经使用Spring AOP成功尝试过,但这不是一个选项,因为我还想将私有方法与我的方面绑定。所以我必须使用更强大的 AspectJ 来实现这一点。

不幸的是,AspectJ Load-Time Weaving对我来说不是一个选项,因为它需要在执行 jar 时将 jvm-arguments 传递给命令行,而我想避免这种情况。

所以从我现在看到的情况来看,只剩下AspectJ Compile-Time WeavingAspectJ Post-Compile-Time Weaving

AspectJ Compile-Time Weaving 看起来最适合我,但不幸的是,必须从 io.freefair 应用如下插件。
链接:https
://plugins.gradle.org/plugin/io.freefair.aspectj.compile-time-weaving 我已经尝试过了,它工作正常,但我的目标是避免向我的项目添加外部依赖项,因此我正在尝试从 Spring 或标准 Java 系列中找到解决方案。

编译后编织也是如此。

我读过的关于编译时编织的每个教程或答案都是关于应用插件的。我想知道我没有找到解决我的用例的方法,除了上面的 io.freefair 插件。

主类:

@SpringBootApplication
@ImportResource("classpath:spring/applicationContext.xml")
@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class })
public class MainClass {

    /**
     * The main method.
     *
     * @param args the arguments
     */
    public static void main(String[] args) {
        SpringApplication.run(MainClass.class, args);
    }
}

我的方面类如下所示:

@Aspect
public class ConfigurationsAspect {

    private static final Logger logger = Logger.getLogger(ConfigurationsAspect.class);

    @Autowired
    private ConnectionWrapper connection;

    @Autowired
    private OptionHandler optionHandler;

    /**
     * Closes the connection to the Server if there were an initialized connection.
     */
    @After("execution(void tools.cli.MainClass.main(*))")
    public void closeConnection() {
        if (this.connection.isConnected()) {
            logger.debug("Closing connection");
            this.connection.close();
        }
    }                                                                                                                       

    /**
     * Parses the options if not parsed before.
     * 
     * @param jp The actual point of execution.
     */
    @Before("execution(* tools.runners.tasks.*.run(*))")
    public void parseOptions(JoinPoint jp) {
        if (!this.optionHandler.isParsed()) {
            String[] args = (String[]) jp.getArgs()[0];
            this.optionHandler.parseParameters(args);
        }
    }
}

所涉及的 bean 在 applicationContext.xml 中描述,如(Snippet):

    <bean class="tools.aspects.ConfigurationsAspect" factory-method="aspectOf"/>    

    <bean class="tools.cli.options.OptionHandler"/>

    <bean class="tools.connection.ConnectionWrapper" />

我的 build.gradle 看起来像这样(片段):

plugins {
    id 'org.springframework.boot' version '2.1.3.RELEASE'
    id 'java'
}

apply plugin: 'application'
apply plugin: 'io.spring.dependency-management'

dependencies {
    compile('commons-io:commons-io:2.5')    
    compile('commons-cli:commons-cli:1.4')
    compile('org.springframework.boot:spring-boot-starter')

    compile('org.springframework:spring-oxm')
    testCompile('org.springframework:spring-oxm')

    compile 'org.aspectj:aspectjrt:1.9.2'
    compile 'org.aspectj:aspectjweaver:1.9.2'
}

当我不应用 io.freefair 插件时,我收到以下错误消息。

ERROR org.springframework.boot.SpringApplication: 858 - Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tools.aspects.ConfigurationsAspect#0' defined in class path resource [spring/applicationContext.xml]: No matching factory method found: factory method 'aspectOf()'. Check that a method with the specified name exists and that it is static.

AspectJ 应该创建我的 ConfigurationsAspect 的实例并插入 aspectOf() 方法,如果它工作正常,Spring 正在搜索该方法。

导致我的问题:

是否有机会在不应用外部依赖项的情况下实现 AspectJ 编译时(或编译后)编织?

如果不是那么,即使我更喜欢编译时编织,是否有机会在没有传递 JVM 参数以正确运行 jar 的情况下实现加载时编织?


谢谢和问候。

4

0 回答 0