7

In a real project, I found out that @Component may be omitted in the following code:

// no @Component !!!!!
public class MovieRecommender {

    private final CustomerPreference customerPreference;

    @Autowired
    public MovieRecommender(CustomerPreference customerPreference) {
        this.customerPreference = customerPreference;
    }

    // ...
}

@Component
public class CustomerPreference {...}

(The example is taken from the official Spring docs https://docs.spring.io/spring-framework/docs/4.3.x/spring-framework-reference/htmlsingle/#beans-autowired-annotation , and the docs show no @Component at all, which may mean either that it is not needed, or that it is just not shown.)

The project where I work does not use any XML bean declarations, but it uses frameworks other than just Spring, so it is possible that something declares the class as a bean. Or it may be a feature of the version of Spring that we use, and if that feature is not documented, it may be dropped later.

Question: Must the class that uses @Autowired be annotated with @Component (well, be a bean)? Is there any official documentation about that?

UPD Folks, there is no @Configuration and no XML configs in the project, I know that such declarations make a bean from a class, but the question is not about them. I even wrote "(well, be a bean)" in the question above to cover that. Does @Autowired work in a class that is not a bean? Or maybe it declares the class that uses it as a bean?

18446744073709551615
  • 16,368
  • 4
  • 94
  • 127
  • 1
    Well if you don't get null pointer exception it seems to be working :) – Shubham Dixit Oct 13 '20 at 13:05
  • There are different ways to create Spring beans. One is by using `@Component` with classpath scanning, other ways are by using XML config or Java config, by having `@Bean` methods in a `@Configuration` class. So the answer is: No, `@Autowired` does not necessarily mean you must also use `@Component`. – Jesper Oct 13 '20 at 13:26
  • Yes, it could be done by `@Bean` annotation in `@Configuration` class but then using `@Autowired` on constructor seems like doesn't have much sense since in Bean definition you have to literally specify what class are you willing to inject there, so there will be no Autowiring. @OP: For me it seems like someone forgot to remove this annotation from you source code after refactored this Component from annotation based to java based configuration. Did you try to remove this `@Autowire`? And btw. Modern IDE should have possibility to show where particular bean is registered. Try that maybe – Zychoo Oct 13 '20 at 13:35
  • It may be registered with `applicationContext.xml` or `@Configuration+@Bean`. – Giorgi Tsiklauri Oct 13 '20 at 16:38
  • `@Autowired` on the construct makes no sense in the above example... _In a real project, I found out that @Component may be omitted in the following code_ Hmm, I don't think so... – Dirk Deyne Oct 13 '20 at 19:46

2 Answers2

4

According to https://stackoverflow.com/a/3813725/755804 , with autowireBean() it is possible to autowire a bean from a class not declared as a bean.

@Autowired
private AutowireCapableBeanFactory beanFactory;

public void sayHello(){
    System.out.println("Hello World");
    Bar bar = new Bar();
    beanFactory.autowireBean(bar);
    bar.sayHello();
}

and

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;

public class Bar {
    @Autowired
    private Foo foo;

    public void sayHello(){
        System.out.println("Bar: Hello World! foo="+foo);
    }
}

On the other hand, by default the latest Spring does not assume that classes that use @Autowire are @Component-s.

UPD As to the mentioned real project, the stack trace shows that the constructor is called from createBean(). That is, the framework creates beans from classes declared in the framework's configs.

18446744073709551615
  • 16,368
  • 4
  • 94
  • 127
2

there are several ways to instantiate a bean in Spring.
One of them indeed is with the @Component annotations, with that, Spring will scan all the packages defined for component-scan and initialize all annotated classes (either with @Component or one of the annotations that uses it - Controller, Service, etc.).

Other way to initialise beans is using a configuration class (annotated with @Configuration) that includes methods annotated with @Bean. each of these methods will create a bean.

There's also an option to create the beans using xml configurations, but this is becoming less and less common, as the annotation-based approach is more convinient

Nir Levy
  • 12,750
  • 3
  • 21
  • 38
  • No `@Configuration` and no xml in the project, only annotations. No single `@Bean`. But `@Autowired` works without `@Component`. – 18446744073709551615 Oct 13 '20 at 14:32
  • @18446744073709551615 then it gets registered somewhere, maybe in some other context, which you scan for the components.. it is impossible to inject the bean which does not exist. There is NO way of that. – Giorgi Tsiklauri Oct 13 '20 at 16:40