31

I am reading the book Pro Spring 3. It has a certain paragraph that really confused me. The paragraph is about autowiring in spring. Here is an excerpt:

In most cases, the answer to the question of whether you should use autowiring is definitely “no!” Autowiring can save you time in small applications, but in many cases, it leads to bad practices and is inflexible in large applications. Using byName seems like a good idea, but it may lead you to give your classes artificial property names so that you can take advantage of the autowiring functionality. The whole idea behind Spring is that you can create your classes how you like and have Spring work for you, not the other way around ...

... For any nontrivial application, steer clear of autowiring at all costs.

I have always been using the @Autowired tag in applications I have created. Can someone explain what is wrong with it and what I should use instead?

A mini example on how I handle most things now is:

@Service("snippetService")
public class SnippetService {

    @Autowired
    private TestService testService;

    public Snippet getSnippet() {
        return testService.getSnippet();
    }
}    

Is using autowiring like this "wrong" or am I missing something?

Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
Geoffrey De Vylder
  • 3,963
  • 7
  • 36
  • 56
  • I am not a Spring user, but i am familiar with Guice and CDI. Those frameworks do essentially nothing but autowiring; for each annotated injection site, the framework will go and find something it can inject, based on type, and on any qualifiers present, and then inject it. People have built really quite large applications using this approach; i work on one. I do not believe they have encountered the problems prophesied by Spring autowire-phobes. – Tom Anderson Oct 16 '12 at 18:26
  • A caveat, though: these frameworks do not do autowiring in the sense of `autowire="byType"`. If, as @mrembisz says, the article is specifically warning against that, then the experience from Guice and CDI is not relevant. – Tom Anderson Oct 16 '12 at 18:27

4 Answers4

26

I believe there are two things confused here. What is meant by 'autowiring' in this chapter is marking bean for automated detection and injection of dependencies. This can be achieved through setting of "autowire" bean attribute.

This is in fact opposed to using @Autowired where you explicitely indicate field or setter for dependency injection.

Have a look here: http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html#beans-factory-autowire.

To explain it, assume you have

public class SnippetService {

    private TestService testService;

    public Snippet getSnippet() {
        return testService.getSnippet();
    }

    public void setTestService(TestService testService) {
      this.testService = testService;
    }
}

If you defined a bean:

<bean class="mypackage.SnippetService" autowire="byType"/>

spring would attempt to inject bean of matching type, TestService in this case, by calling setTestService setter. Even though you did not use @Autowired. This indeed is dangerous since some setters might not be meant to be called by spring.

If you set autowire="no", nothing will be injected unless marked so with @Autowired, @Resource, @Inject.

mrembisz
  • 12,722
  • 7
  • 36
  • 32
  • 1
    That makes more sense. I had this situation just come up. I wanted to read values from a property file and inject them into a bean. Only way I could figure out how to do this at start up of my app was to wire the bean in XML (and inject the properties.) I ended up using the "byName" attribute (because the bean was also marked as @Component) and then used @Autowired @Qualifier("nameIChose") when injecting the bean into another class. It's the only bean I've written that I wire with XML. – Marvo Oct 16 '12 at 18:19
  • I've found autowiring useful in cases where I've had a factory bean making another bean (whose implementation class name was described in a system property, so I couldn't define the all wiring in XML). I usually prefer to make my wiring explicit though; it greatly simplifies long-term maintenance if things are explicit. – Donal Fellows Oct 17 '12 at 09:40
3

There's nothing wrong with what you have, especially if you are starting out with one implementation of TestService anyways. As Johan mentions though, it's better to use @javax.annotation.Resource which also allows you to be more specific if you need to (for example using the name or the type attribute).

Abdullah Jibaly
  • 53,220
  • 42
  • 124
  • 197
  • 2
    The use of `@Qualifier` is discouraged in favour of `@Resource` – Johan Sjöberg Oct 16 '12 at 18:06
  • Since Spring IoC container implements JSR 250, does this make a case to use @Resource all the time as opposed to @Autowired? Edit: apparently it depends (surprise!) Interesting forum post http://forum.springsource.org/showthread.php?48563-Autowired-and-Resource-difference – dardo Oct 16 '12 at 18:16
  • It would definitely seem so, especially if you can stick with field or setter method injection. – Abdullah Jibaly Oct 16 '12 at 18:23
  • I have never come across the @Resource annotation. Thanks for mentioning it and explaining its use. – Geoffrey De Vylder Oct 16 '12 at 20:06
2

The only problem I see here is that you are loosing control a little. For example, say you have two or more instances of TestService in your app config and you want to use one of them. Having Autowire makes is trickier than using config XML to inject for you. This is what your book is trying to point i.e. it becomes difficult/trickier in big application where such needs are more frequent.

If you don't have such situations, I think its fine.

Yogendra Singh
  • 33,927
  • 6
  • 63
  • 73
  • 1
    But what you do in that situation is use the @Qualifier annotation to indicate which of those beans you want. – Marvo Oct 16 '12 at 18:15
  • I didn't say you can't do that. All I meant is that: config files were meant to inject and use the dependencies externally. By using `annotations`, we bring that into implementation class itself. This becomes difficult/trickier in bigger applications. – Yogendra Singh Oct 16 '12 at 18:21
  • 1
    I think that's subjective. I find not having to maintain large cumbersome XML files to be far more difficult. And if a new implementation for a particular interface is required, I would have to change the XML and the class; with autowiring, I would simply replace the class. One less change, one less possible bug. – Marvo Oct 16 '12 at 18:38
0

Autowire through XML is completely safe and helpful if you do constructor based autowiring particularly if you make the collaborators private final.

I'm kind shocked the author said that when I did the above on an extremely large spring 2.5 project a couple years ago. (at the time the annotation support was not working in JBoss)

Adam Gent
  • 47,843
  • 23
  • 153
  • 203