Difference between @Bean and @Autowired
Asked Answered
T

6

133

Why can't I use @Autowired in this case?

@SpringBootApplication
public class Application {

    @Autowired
    BookingService bookingService;

    public static void main(String[] args) {
        bookingService.book("Alice", "Bob", "Carol");
    }
}

but can use @Bean

@SpringBootApplication
public class Application {

    @Bean
    BookingService bookingService() {
        return new BookingService();
    }

    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(Application.class, args);
        BookingService bookingService = ctx.getBean(BookingService.class);
        bookingService.book("Alice", "Bob", "Carol");
    }
}

Aren't the two ways to generate BookingService the same thing?

Turbosupercharger answered 9/12, 2015 at 7:21 Comment(2)
Bean annotation is for registering your bean in the spring context whereas Autowried annotation is for getting the bean from spring application content and wiring it as a dependency for another objectOntologism
You should deliver the BookingService class too. Because if that is annotated with Component then your first class would also work like the second.Ayannaaycock
I
268

@Bean and @Autowired do two very different things. The other answers here explain in a little more detail, but at a simpler level:

  • @Bean tells Spring 'here is an instance of this class, please keep hold of it and give it back to me when I ask'.

  • @Autowired says 'please give me an instance of this class, for example, one that I created with an @Bean annotation earlier'.

Does that make sense? In your first example, you're asking Spring to give you an instance of BookingService, but you're never creating one, so Spring has nothing to give you. In your second example, you're creating a new instance of BookingService, telling Spring about it, and then, in the main() method, asking for it back.

If you wanted, you could remove the two additional lines from the second main() method, and combine your two examples as below:

@SpringBootApplication
public class Application {

  @Autowired
  BookingService bookingService;

  @Bean
  BookingService bookingService() {
    return new BookingService();
  }

  public static void main(String[] args) {
    bookingService.book("Alice", "Bob", "Carol");
  }
}

In this case, the @Bean annotation gives Spring the BookingService, and the @Autowired makes use of it.

This would be a slightly pointless example, as you're using it all in the same class, but it becomes useful if you have the @Bean defined in one class, and the @Autowired in a different one.

Impeachable answered 9/12, 2015 at 9:13 Comment(5)
Somehow that answer appear only partly correct to me. Autowired can also call Objects annotated with @Components. Moreover Autowired can be used for Methods not only for objects.Ayannaaycock
@PowerFlower, absolutely right, my point here was to explain the difference in the context of the question. Certainly there is plenty more complexity in both annotations, but I was trying to give a simple, high-level explanation for this specific example.Impeachable
This answer is wrong. Not sure why it has so many upvotes. Bean and autowire are interchangeable in most cases. Check my answer below.Torres
So in your example, the execution order of Bean and Autowired is Bean before Autowired?Bathilda
@LiYingjun, you could think of it that way, yes. I think it's fair to say that any method annotated with @Bean will be run before any autowiring happens - that's essential because Spring uses the objects created as @Beans (as well as @Services, @Components, etc) to inject into the appropriate @Autowired targets.Impeachable
C
26
@Bean
BookingService bookingService() {
    return new BookingService();
}

Annotating @Bean only registers the service as a bean(kind of an Object) in the spring application context. In simple words, it is just registration and nothing else.

@Autowired
BookingService bookingService;

Annotating a variable with @Autowired injects a BookingService bean(i.e Object) from Spring Application Context.

(i.e) The registered object with @Bean annotation will be injected to the variable annotated with @Autowired.

Hope this clears your doubt!

Course answered 9/12, 2015 at 7:47 Comment(4)
but I can't use BookingService's fucntion if I inject BookingService with @AutowiredTurbosupercharger
Now I know it is because in the main() I got error "change modifier of book() to static" ,I can use BookingService's object in other functions.But I don't whyTurbosupercharger
@zhuochenshen I am not sure what is inside of you class and current problem. I answered only your "difference" question. You can post another question regarding to your next problem.Course
I.E,registered bean with @Bean will be inject to the variable annotated with @Autowired. This line turns out to be the essence of all what these two annotations are about.Xhosa
K
8

great answer by @DaveyDaveDave In the example instead of

@Bean
  BookingService bookingService() {
    return new BookingService();
  }

You can use @Service annotation on BookingService class

Kovach answered 14/3, 2017 at 21:48 Comment(0)
T
7

Contrary to what the highest voted answer here claims, they are NOT two very different things. @Bean and @Autowired and interchangeable in most cases.

Suppose you have a @Bean method that returns an instance of a Car. You can literally get rid of that bean method and add @Component on the Car class and then autowire it.

And vice versa. Whatever class you have instantiated using @Autowired, you can instantiate it inside a class with @Configuration annotation using @Bean on the method.

Places where you will use @Bean instead of @Autowired

1>You do not have access to change the class to add @Component annotation, hence you cannot autowire it.

2>You want to customize the instantiation of the class.

For example if you are instantiating a Resilience4J Circuit breaker class, if you do it inside a method with @Bean, you have the option of setting all the config using code like this

@Bean
public CircuitBreaker fooCircuitBreaker() {
    CircuitBreakerConfig.Builder builder = CircuitBreakerConfig.custom().
            slidingWindowSize(xxx).
            failureRateThreshold(xxx).
            waitDurationInOpenState(xxx)).
            ignoreException(e -> {
                if (e instanceof HttpStatusCodeException) {
                    HttpStatusCodeException httpStatusCodeException = (HttpStatusCodeException) e;
                    if (httpStatusCodeException.getStatusCode().is4xxClientError()) {
                        return true;
                    }
                }
                return false;
            });
    circuitBreakerRegistry.addConfiguration(xxx, builder.build());
    return circuitBreakerRegistry.circuitBreaker(xxx, xxx);
}
Torres answered 9/9, 2020 at 22:7 Comment(3)
Sorry, but I think you're wrong here. Perhaps you've misunderstood what I mean by "very different", maybe "two sides of the same coin" would be more appropriate. But certainly, they are not interchangeable. @Bean and @Component are (sort of) interchangeable in that they both register beans, but @Autowired doesn't register a bean. If you have an example where you could use them interchangeably, then maybe edit your answer to include it?Impeachable
@Impeachable If you have a pluralsight subscription, watch this spring fundamentals course by Bryan Hansen. In this tutorial he first wires up beans using Bean annotation and then he introduces Autowired annotation where he gets rid of Bean annotations. app.pluralsight.com/library/courses/…Torres
Right, but those @Autowired annotations are in completely different places from the @Bean annotations that get removed, right? Because they're not interchangeable. They're different. They achieve similar things, in that they provide dependency injection functionality, but they perform different jobs. Again, in very simple terms - @Bean registers an object with Spring, @Autowired tells Spring where to use it.Impeachable
R
3

Here's good article about @Autowired annotation: http://www.baeldung.com/spring-autowire

The @Autowired annotation can instantiate your injectables by defining @ComponentScan("namespace.with.your.components.for.inject") on config class

@Configuration
@ComponentScan("com.baeldung.autowire.sample")
public class AppConfig {}

All components must be marked by @Component annotation. It replaces the @Bean annotation.

Reprography answered 29/3, 2018 at 20:5 Comment(0)
W
1

@Bean is just for the metadata definition to create the bean(equivalent to tag). @Autowired is to inject the dependancy into a bean(equivalent to ref XML tag/attribute).

Weary answered 2/5, 2019 at 18:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.