The article directories

    • preface
    • methods
      • 1. @ PostConstruct annotation
      • 2. The InitializingBean interface
      • 3. ApplicationListener
      • 4. @bean and initMethod properties
      • Constructor injection
      • 6. CommandLineRunner
      • 7. ApplicationRunner
    • Combining with the mechanism

preface

It is a common requirement to run some of our custom logic during SpringBoot startup, but not knowing when a component is running can cause a lot of problems.

After instantiating any object, we cannot simply include the logic in the bean’s constructor or in the calling method. We have no control over these processes.

Let’s look at a real example:

@Component
public class InvalidInitExampleBean {

    @Autowired
    private Environment env;

    public InvalidInitExampleBean(a) { env.getActiveProfiles(); }}Copy the code

Here we try to access the autowire field in the constructor. When the constructor is called, the Spring bean is not fully initialized. This is a problem because calling an uninitialized field of course causes a null-pointer exception.

methods

Spring provides some ways to manage this situation.

1. @ PostConstruct annotation

Can be used to annotate methods that run once immediately after the bean is initialized. Keep in mind that annotated methods will be executed by Spring even without any injection.

This is what * @postconstruct * does:

@Component
public class PostConstructExampleBean {

    private static final Logger LOG 
      = Logger.getLogger(PostConstructExampleBean.class);

    @Autowired
    private Environment environment;

    @PostConstruct
    public void init(a) { LOG.info(Arrays.asList(environment.getDefaultProfiles())); }}Copy the code

In the example above, you can see that the environment instance is safely injected and then called in the annotated * @postconstruct method without raising NullPointerException*.

2. The InitializingBean interface

Applies similarly to the previous one. Instead of annotating methods, you need to implement the InitializingBean interface and the *afterPropertiesSet () * method.

Here you can see a previous example of an implementation using the InitializingBean interface:

@Component
public class InitializingBeanExampleBean implements InitializingBean {

    private static final Logger LOG 
      = Logger.getLogger(InitializingBeanExampleBean.class);

    @Autowired
    private Environment environment;

    @Override
    public void afterPropertiesSet(a) throws Exception { LOG.info(Arrays.asList(environment.getDefaultProfiles())); }}Copy the code

3. ApplicationListener

This approach can be used to run logic after the Spring context has been initialized, so we don’t focus on any particular beans and wait for all of them to be initialized.

To do this, you need to create a bean that implements the *ApplicationListener * interface:

@Component
public class StartupApplicationListenerExample implements 
  ApplicationListener<ContextRefreshedEvent> {

    private static final Logger LOG 
      = Logger.getLogger(StartupApplicationListenerExample.class);

    public static int counter;

    @Override public void onApplicationEvent(ContextRefreshedEvent event) {
        LOG.info("Increment counter"); counter++; }}Copy the code

The same result can be achieved by using the newly introduced * @eventListener * annotation:

@Component
public class EventListenerExampleBean {

    private static final Logger LOG 
      = Logger.getLogger(EventListenerExampleBean.class);

    public static int counter;

    @EventListener
    public void onApplicationEvent(ContextRefreshedEvent event) {
        LOG.info("Increment counter"); counter++; }}Copy the code

In this example, we selected *ContextRefreshedEvent. * Make sure you choose the right activities for your needs.

4. @bean and initMethod properties

This and initMethod properties can be used for methods executed after the Bean’s initialization.

public class InitMethodExampleBean {
    private static final Logger LOG = Logger.getLogger(InitMethodExampleBean.class);

    @Autowired
    private Environment environment;

    public void init(a) { LOG.info(Arrays.asList(environment.getDefaultProfiles())); }}Copy the code

You’ll notice that no special interfaces are implemented and no special annotations are used.

We can then define the Bean with the * @bean * notation:

@Bean(initMethod="init")
public InitMethodExampleBean initMethodExampleBean(a) {
    return new InitMethodExampleBean();
}
Copy the code

This is how the bean definition looks in an XML configuration:

<bean id="initMethodExampleBean"
  class="com.baeldung.startup.InitMethodExampleBean"
  init-method="init">
</bean>
Copy the code

Constructor injection

If you want to use constructor injection to inject fields, you simply include logic in the constructor:

@Component 
public class LogicInConstructorExampleBean {

    private static final Logger LOG 
      = Logger.getLogger(LogicInConstructorExampleBean.class);

    private final Environment environment;

    @Autowired
    public LogicInConstructorExampleBean(Environment environment) {
        this.environment = environment; LOG.info(Arrays.asList(environment.getDefaultProfiles())); }}Copy the code

6. CommandLineRunner

Spring startup provides a method for the CommandLineRunner interface with a callback *run () * method that can be called at application startup after instantiating the Spring application context.

Let’s look at an example:

@Component
public class CommandLineAppStartupRunner implements CommandLineRunner {
    private static final Logger LOG =
      LoggerFactory.getLogger(CommandLineAppStartupRunner.class);

    public static int counter;

    @Override
    public void run(String... args) throws Exception {
        LOG.info("Increment counter"); counter++; }}Copy the code

Note: As described in the documentation, multiple CommandLineRunner beans can be defined in the same application context and can be Ordered * using the * @ordered interface or the @Order annotation.

7. ApplicationRunner

Similar to CommandLineRunner *, the Spring boot also provides an ApplicationRunner interface with the Run () method, which is called when the application starts. Instead of a raw String argument passed to the callback method, however, we have instances of the ApplicationArguments class.

The ApplicationArguments interface has methods that get options and simple parameter values for parameter values. Arguments prefixed with — are option arguments.

Let’s look at an example:

@Component
public class AppStartupRunner implements ApplicationRunner {
    private static final Logger LOG =
      LoggerFactory.getLogger(AppStartupRunner.class);

    public static int counter;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        LOG.info("Application started with option names : {}", 
          args.getOptionNames());
        LOG.info("Increment counter"); counter++; }}Copy the code

Combining with the mechanism

To achieve full control over beans, you may need to combine the above mechanisms.

The execution sequence is as follows:

  1. The constructor
  2. Annotated methods in * @postconstruct *
  3. InitializingBean’s *afterPropertiesSet () * method
  4. In XML, it meansinit-methodThe initialization method of

Let’s create a Spring bean that combines all the mechanisms:

@Component
@Scope(value = "prototype")
public class AllStrategiesExampleBean implements InitializingBean {

    private static final Logger LOG 
      = Logger.getLogger(AllStrategiesExampleBean.class);

    public AllStrategiesExampleBean(a) {
        LOG.info("Constructor");
    }

    @PostConstruct
    public void postConstruct(a) {
        LOG.info("PostConstruct");
    }
    
    @Override
    public void afterPropertiesSet(a) throws Exception {
        LOG.info("InitializingBean");
    }

    public void init(a) {
        LOG.info("init-method"); }}Copy the code

If you try to instantiate this bean, you will be able to view the logs that match the order specified above:

[main] INFO o.b.startup.AllStrategiesExampleBean - Constructor
[main] INFO o.b.startup.AllStrategiesExampleBean - PostConstruct
[main] INFO o.b.startup.AllStrategiesExampleBean - InitializingBean
[main] INFO o.b.startup.AllStrategiesExampleBean - init-method
Copy the code

www.baeldung.com/running-set…


🍎QQ group [837324215] 🍎 pay attention to my public number [Java Factory interview officer], learn together 🍎🍎🍎 🍎 personal vx [Lakernote]