简体   繁体   中英

Access annotated class member from main method

In my Spring Boot application, I want to access my class's member variable (annotated as @Value , since it's a property being read from a properties file) from the main method. Since the static main method cannot read non-static variables, I made the variable static as well.

Edit : I also need to close the ApplicationContext returned by SpringApplication.run() based on the value of this property. I am updating the code below to reflect this.

My code looks something like this:

@SpringBootApplication
public class Application {

// the variable I want to access in main
@Value("{property:}")
protected static String property;

public static void main(String[] args) throws Exception {
    ConfigurableApplicationContext context = SpringApplication.run(AccountApiApplication.class, args);

    if(new String("true").equals(property)) {
        SpringApplication.exit(context)
    }
}

Edit : There are two issues here:

  1. property can't be static (as opposed to the code above), or the @Value annotation won't work with it. And I can't make it non-static, since then it won't be accessible from main .

  2. I have been suggested a couple different approaches, which I'm considering for shutting down the ApplicationContext, but they might not work for me:

    - Using a @PostConstruct annotated init() method. Trouble is, I don't think the ConfigurableApplicationContext returned by main() can be accessed here.

    - Using CommandLineRuuner.run() or ApplicationRunner.run() . These run() methods seem to be executing before my Spring Batch job even starts, so I can't use these to shut down the ApplicationContext, or the application would be shut down even before my jobs execute.

You cannot inject value expression in a static field (as well as for Spring components).

So the @Value field should be an instance field. In order to be able to access to it, you should do that from an instance method as you guessed.

Note that to be able to manipulate the running ApplicationContext instance, the Spring context has to be completely initialized.

To achieve it, you should invoke the instance method that manipulates the ApplicationContext only after SpringApplication.run() is returned.
You should first retrieve the bean corresponding to the current application class by using the BeanFactory.getBean() method.
Then, you could invoke the instance method that needs the ApplicationContext :

@SpringBootApplication
public class Application {

    @Value("{property:}")
    protected String property;

    public static void main(String[] args) throws IOException {
        ConfigurableApplicationContext context = SpringApplication.run(AccountApiApplication.class, args);
        AccountApiApplication app = context.getBean(AccountApiApplication.class);
        app.doMyTask(context);
    }

    public void doMyTask(ConfigurableApplicationContext context)  {
      if(property) {
          context.close();
      }
      else {
        // do something else
      }

    }
}

Injection into static variables doesn't work with Spring. There would be workarounds, but in your case they also wouldn't work. If you want to execute code after the startup of your application, create a new class which implements the ApplicationRunner interface ( https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-spring-application.html#boot-features-command-line-runner ). That exists for exactly your usecase.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM