Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Dependency injection: XML or annotations

Annotations becoming popular. Spring-3 supports them. CDI depends on them heavily (I can not use CDI with out of annotations, right?)

My question is why?

I heard several issues:

  1. "It helps get rid of XML". But what is bad about xml? Dependencies are declarative by nature, and XML is very good for declarations (and very bad for imperative programming). With good IDE (like idea) it is very easy to edit and validate xml, is not it?

  2. "In many cases there is only one implementation for each interface". That is not true! Almost all interfaces in my system has mock implementation for tests.

Any other issues?

And now my pluses for XML:

  1. You can inject anything anywhere (not only code that has annotations)

  2. What should I do if I have several implementations of one interface? Use qualifiers? But it forces my class to know what kind of injection it needs. It is not good for design.

XML based DI makes my code clear: each class has no idea about injection, so I can configure it and unit-test it in any way.

What do you think?

like image 771
Ilya K Avatar asked Feb 14 '11 17:02

Ilya K


People also ask

Is XML better than annotation?

The biggest disadvantage of XML is indeed its size. Multiple lines are needed for things that you can do in one simple annotation. They are far away from the part in the code where it applies, whereas annotations are just on top of them. So annotations seem a lot more logical and simpler.

Which is better annotation or XML in Spring?

From my own experience annotations better than xml configuration. I think in any case you can override xmls and use annotations. Also Spring 4 give us a huge support for annotations, we can override security from xml to annotations e.t.c, so we will have not 100 lines xml but 10 lines Java Code.

Which annotations are used for dependency injection?

Dependency injection is simply an easier-to-program alternative to using the javax interfaces or JNDI APIs to look up resources. A field or a method of an application component can be annotated with the @Resource annotation.

What is difference between XML and annotation in Spring?

So instead of using XML to describe a bean wiring, you can move the bean configuration into the component class itself by using annotations on the relevant class, method, or field declaration. Annotation injection is performed before XML injection.


2 Answers

I can only speak from experience with Guice, but here's my take. The short of it is that annotation-based configuration greatly reduces the amount you have to write to wire an application together and makes it easier to change what depends on what... often without even having to touch the configuration files themselves. It does this by making the most common cases absolutely trivial at the expense of making certain relatively rare cases slightly more difficult to handle.

I think it's a problem to be too dogmatic about having classes have "no idea about injection". There should be no reference to the injection container in the code of a class. I absolutely agree with that. However, we must be clear on one point: annotations are not code. By themselves, they change nothing about how a class behaves... you can still create an instance of a class with annotations as if they were not there at all. So you can stop using a DI container completely and leave the annotations there and there will be no problem whatsoever.

When you choose not to provide metadata hints about injection within a class (i.e. annotations), you are throwing away a valuable source of information on what dependencies that class requires. You are forced to either repeat that information elsewhere (in XML, say) or to rely on unreliable magic like autowiring which can lead to unexpected issues.

To address some of your specific questions:

It helps get rid of XML

Many things are bad about XML configuration.

  • It's terribly verbose.
  • It isn't type-safe without special tools.
  • It mandates the use of string identifiers. Again, not safe without special tool support.
  • Doesn't take any advantage of the features of the language, requiring all kinds of ugly constructs to do what could be done with a simple method in code.

That said, I know a lot of people have been using XML for long enough that they are convinced that it is just fine and I don't really expect to change their minds.

In many cases there is only one implementation for each interface

There is often only one implementation of each interface for a single configuration of an application (e.g. production). The point is that when starting up your application, you typically only need to bind an interface to a single implementation. It may then be used in many other components. With XML configuration, you have to tell every component that uses that interface to use this one particular binding of that interface (or "bean" if you like). With annotation-based configuration, you just declare the binding once and everything else is taken care of automatically. This is very significant, and dramatically reduces the amount of configuration you have to write. It also means that when you add a new dependency to a component, you often don't have to change anything about your configuration at all!

That you have mock implementations of some interface is irrelevant. In unit tests you typically just create the mock and pass it in yourself... it's unrelated to configuration. If you set up a full system for integration tests with certain interfaces using mocks instead... that doesn't change anything. For the integration test run of the system, you're still only using 1 implementation and you only have to configure that once.

XML: You can inject anything anywhere

You can do this easily in Guice and I imagine you can in CDI too. So it's not like you're absolutely prevented from doing this by using an annotation-based configuration system. That said, I'd venture to say that the majority of injected classes in the majority of applications are classes that you can add an @Inject to yourself if it isn't already there. The existence of a lightweight standard Java library for annotations (JSR-330) makes it even easier for more libraries and frameworks to provide components with an @Inject annotated constructor in the future, too.

More than one implementation of an interface

Qualifiers are one solution to this, and in most cases should be just fine. However, in some cases you do want to do something where using a qualifier on a parameter in a particular injected class would not work... often because you want to have multiple instances of that class, each using a different interface implementation or instance. Guice solves this with something called PrivateModules. I don't know what CDI offers in this regard. But again, this is a case that is in the minority and it's not worth making the rest of your configuration suffer for it as long as you can handle it.

like image 128
ColinD Avatar answered Sep 18 '22 17:09

ColinD


I have the following principle: configuration-related beans are defined with XML. Everything else - with annotations.

Why? Because you don't want to change configuration in classes. On the other hand, it's much simpler to write @Service and @Inject, in the class that you want to enable.

This does not interfere with testing in any way - annotations are only metadata that is parsed by the container. If you like, you can set different dependencies.

As for CDI - it has an extension for XML configuration, but you are right it uses mainly annotations. That's something I don't particularly like in it though.

like image 21
Bozho Avatar answered Sep 22 '22 17:09

Bozho