1

Is there any good reason to not look up an object in application context instead of "suppose" a dependency was injected? Ex:

public Dependency getDependency(){
     if (dependency  == null){
        dependency = (Dependency) applicationContext.getBean("dependency");
     }
     return dependency;
}

Debatable arguments

Polluting object with Spring specific object

Some people could complain that using application context will bind the implementation with Spring stuffs. BUT, it could be trivially solved creating a indirection to applicationContext. Ok... let me exemplify:

public Dependency getDependency(){
     if (dependency  == null){
        dependency = (Dependency) serviceLocator.getBean("dependency");
     }
     return dependency;
}

Hard to change implementation

First, it (the dependency object) could be easily changed in application context. But, even easier a mock could be insert directly using the usual mutator:

public void setDependency(Dependency dep){
     this.dependency = dep;
}

Historical question

Long time ago, everybody in Java world was using Service Locator (in a directory service by a technology called JNDI) to have a interchangeable object infrastructure. We could bind in the directory service three kind of objects: serializable data, reference or Dircontext. It would additionally allow you to look up objects in distributed environment.

Then, we have the Spring revolution and now DI (Dependency injection) is used most of the cases.

However, the service locator pattern was not prohibited by Spring. For instance, using ApplicationContext allow us to look up the beans in a service locator way. We could think that the Spring framework provides a big factory of objects with a centralized configuration, the dependency injection facility but also a directory of services that could be easily handle. The last part has been almost forgotten.

Related Question

Why is Spring's ApplicationContext.getBean considered bad?

I am not considering that because those answers although edifying , they are not enlightening the points raise above.

Nimantha
  • 6,405
  • 6
  • 28
  • 69
rdllopes
  • 4,897
  • 4
  • 19
  • 36
  • My first argument is that DI is much easier than service locator, especially when using annotation based configuration. – fps Mar 13 '15 at 11:19
  • Yeah. It should be. but it is not so easy when have to integrate for example hibernate and spring in a non anemic domain: http://jblewitt.com/blog/?p=129 – rdllopes Mar 13 '15 at 11:26
  • 2
    A read (amongst others) http://martinfowler.com/articles/injection.html#ServiceLocatorVsDependencyInjection – GPI Mar 13 '15 at 11:27
  • @rdllopes That article is quite outdated and seems overkill to me. Spring has evolved a lot from 2009, as well as Java. Anyways, I don't see why you'd need entities to also be Spring beans. You could let Spring inject controllers, configuration, facade handlers (or services), repositories, hibernate's session, transaction manager, etc, while letting Hibernate fetch entities and resolve all the associations between them. Best of both worlds, IMHO, and you'd stick to DDD if you implemented business logic in the entities. – fps Mar 13 '15 at 12:26
  • @mangmag Consider that some domain object could need some service collaborators and the state of a same object could somehow be persisted into and recovered from database. – rdllopes Mar 13 '15 at 13:22

2 Answers2

1

My personal view on this. ease of use of DI via annotation versus having to get the bean via applicationContext. But at the end of the day, I think that the main difference is how the dependencies are located. Service Location entails a client code request for the related specific dependency , whereas using dependency injection the container creates all of objects and injects those dependency as constructor parameters. Frankly at the end of the day both are feasible, but consider this: as far as I know JNDI lookup are pretty expensive in terms of performance so ultimately you are advised to cache them.

witchedwiz
  • 295
  • 2
  • 10
  • The big advantage of DI over Service Location is client code doesn't know how it's dependencies are located. Clients just wait for them to show up. Therefor you can change how they show up without fiddling with your clients. – candied_orange Dec 24 '15 at 14:06
0

Injected service components are simpler than ones that use service locators, and simpler is usually better engineering. Beans that use dependency injection are just regular old Java objects that (sometimes) happen to have @Inject annotated on a constructor (Spring JavaConfig beans may not even need any of that). The bean has no need to manually interface with lookup code, and if you need to alter the dependency that you're passing to it (say, so that you can inject a mock), a bean that's managing its own dependencies will need a lot more infrastructure just to get built.

chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
  • Yeah... For the first argument I somehow agree. Let us say that injected service components hide the complexity of dependency obtainment. The magic @Inject annotation is just a part of whole magic. But, alter the dependency is the same level of difficult. Solution 1) set directly the object as I propose in "Hard to change implementation" part. Or 2) bind in directory service a different object for different context (same as creating a spring context only for test - and yes, it is a common practice). – rdllopes Mar 13 '15 at 13:32
  • @rdllopes Spring *does* support injecting (and changing) via mutators. But if you're setting up a unit test where you're mocking some or all of the dependencies, the service-locator pattern requires setting up a registry instead of just instantiating your bean with mocks. – chrylis -cautiouslyoptimistic- Mar 13 '15 at 14:01
  • sorry @chrylis ... I don't get your point. Let a unit test to target a class which use service-locator to get some collaborators. I can set directly this collaborators via mutators. The trick is verifying if the object was already set in accessor methods. if (dependency == null){ dependency = (Dependency) serviceLocator.getBean("dependency"); } Using DI, I always assume that all dependency has already injected. Using Service-Locator, I have just to remove that assumption. – rdllopes Mar 13 '15 at 14:17
  • I got the point... basically it is the facility with the annotation over the programmatic stuff. – rdllopes Mar 13 '15 at 21:51