Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CommandLineRunner and Beans (Spring)

Tags:

spring

code what my question is about:

   @SpringBootApplication
public class Application {

    private static final Logger log = LoggerFactory.getLogger(Application.class);

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

    @Bean
    public Object test(RestTemplate restTemplate) {
        Quote quote = restTemplate.getForObject(
                "http://gturnquist-quoters.cfapps.io/api/random", Quote.class);
        log.info(quote.toString());
        return new Random();
    }

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder.build();
    }

    @Bean
    public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
        return args -> {
            Quote quote = restTemplate.getForObject(
                    "http://gturnquist-quoters.cfapps.io/api/random", Quote.class);
            log.info(quote.toString());
        };
    }
}

I'm very new to Spring. As far as I understood the @Bean annotation is responsible that an Object is saved in a IoC container, correct?

If so: Are first all Methods with @Bean collected and then executed?

In my example I added a method test() what does the same as run() but returns an Object (Random()) instead. The result is the same so it is working with CommandLineRunner and Object.

Is there a Reason why it should return a CommandLineRunner i.e. use the syntax like run()?

Moreover: At that point I don't see so far the advantage to move methods to an container. Why not just execute it?

Thank you!

like image 972
PowerFlower Avatar asked Apr 14 '17 17:04

PowerFlower


People also ask

What is CommandLineRunner in Spring?

CommandLineRunner is a simple Spring Boot interface with a run method. Spring Boot will automatically call the run method of all beans implementing this interface after the application context has been loaded.

Why do we use CommandLineRunner in Spring boot?

Interface CommandLineRunner This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference. Interface used to indicate that a bean should run when it is contained within a SpringApplication .

What is difference between CommandLineRunner and ApplicationRunner?

ApplicationRunner takes ApplicationArgument which has convenient methods like getOptionNames(), getOptionValues() and getSourceArgs(). CommandLineRunner run() will get execute, just after applicationcontext is created and before spring boot application starts up.

What is @bean annotation in Spring boot?

One of the most important annotations in spring is the @Bean annotation which is applied on a method to specify that it returns a bean to be managed by Spring context. Spring Bean annotation is usually declared in Configuration classes methods. This annotation is also a part of the spring core framework.


1 Answers

@Configuration classes (@SpringBootApplication extends @Configuration) are the place where the spring beans are registered. @Bean is used to declare a spring bean. The method that is annotated with @Bean has to return an object(the bean). By default the spring beans are singletons, so once the method annotated with @Bean is executed and returns it's value this object lives til the end of the application.

In your case

    @Bean
    public Object test(RestTemplate restTemplate) {
        Quote quote = restTemplate.getForObject(
                "http://gturnquist-quoters.cfapps.io/api/random", Quote.class);
        log.info(quote.toString());
        return new Random();
    }

this will produce s singleton bean of type Random with name 'test'. So if you try to inject (e.g. with @Autowire) a bean of that type or name in other spring bean you will get that value. So this is not a good use of @Bean annotation, unless you want exactly that.

CommandLineRunner on the other hand is a special bean that lets you execute some logic after the application context is loaded and started. So it makes sense to use the restTemplate here, call the url and print the returned value.

Not long ago the only way to register a Spring bean was with xml. So we had an xml files and bean declarations like this:

<bean id="myBean" class="org.company.MyClass">
  <property name="someField" value="1"/>
</bean>

The @Configuration classes are the equivalent of the xml files and the @Bean methods are the equivalent of the <bean> xml element.

So it's best to avoid executing logic in bean methods and stick to creating objects and setting their properties.

like image 144
Evgeni Dimitrov Avatar answered Sep 20 '22 00:09

Evgeni Dimitrov