8

can anyone tell me why @autowired is saying field injection is not recommended and the TextWriter object 'text' also says it could not autowire because there is more than one bean of textwriter type.

@RestController
public class HelloWorld{

    @Autowired
    TextWriter text

    public HelloWorld(TextWriter text){
        this.text = text;
    }
    
    @RequestMapping("/")
    public String index(){
        return "Hello World";
    }
}
Wizard
  • 462
  • 1
  • 6
  • 14
  • 2
    Please add your code here do not use the link for that later the link can die and the question is not useful anymore. Plus that code is so small – PedroAGSantos Jul 11 '20 at 05:36
  • 2
    Yes, please put your code in the question as text not an image – tgdavies Jul 11 '20 at 06:40
  • Just create setter for the filed and move @Autowired on it. Your IDE like IDEA will complains about injection, because field is package private, so there is no classical Java way to change it. – Paul Verest Apr 13 '23 at 15:44
  • For the second part of question see https://stackoverflow.com/questions/37565186/spring-couldnt-autowired-there-is-more-than-one-bean-of-type – Paul Verest Apr 13 '23 at 15:46

2 Answers2

9

can anyone tell me why @autowired is saying field injection is not recommended ?

For a design reason. Injecting beans directly into fields makes your dependencies "hidden" and encourage bad design :

  • the class API (public/protected member) doesn't specify them while they exist.
  • no way to unit test without reflection or a Spring container (the most important part for me)
  • you may finish by declaring potentially many injected fields. Which may make your class with a strong coupling to other classes without that you are "really" aware of that.

Generally constructor injection should be favored (no need to annotate the constructor with @Autowired since Spring 4) if few fields, otherwise setters should be the way.
Both ways don't have all drawbacks mentioned above.

davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • 2
    So you inject services called by your Spring class through the constructor ??!! ```java public class MyClass { private Service1 service1; private Service2 service2; private Service3 service3; private Service4 service4; private Service5 service5; private Service6 service6; public MyClass(Service1 service1, Service2 service2, Service3 service3, Service4 service4, Service5 service5, Service6 service6) { this.service1 = service1; this.service2 = service2; this.service3 = service3; this.service4 = service4; this.service5 = service5; this.service6 = service6; } } ``` – Marc Le Bihan Oct 03 '20 at 05:24
  • @Marc Le Bihan Never. Please read carefully : "Generally constructor injection should be favored (no need to annotate the constructor with `@Autowired` since Spring 4) if few fields, otherwise setters should be the way." – davidxxx Oct 03 '20 at 09:13
  • Note: In case of using a Lombok, You can just add @AllArgsConstructor before class and all private fields will be autowired through implicit constructor. – Nashev Aug 03 '21 at 14:54
  • this is rather bad reason to spam this – Enerccio Mar 16 '23 at 12:36
0

I assume Spring does not see your TextWriter class as a bean. Probably TextWriter is in another package. For example, in the “models” package. If you use Spring Boot, then this will help you:

@SpringBootApplication(scanBasePackages={"com.programwithwaqas.restservice.models"})

I recommend you read the @SpringBootApplication annotation. Pay attention to the annotation @ComponentScan.

This is in case you are not using Spring Boot

@ComponentScan(basePackages={"com.programwithwaqas.restservice.models"})
  • While tho OP doesn't show the actual error message, it sounds as though there are several beans implementing the TextWriter interface, rather than none. – tgdavies Jul 11 '20 at 09:52