views:

50

answers:

3

I have a domain model that consists of fairly large object graphs, where domain objects are creating other domain objects and so forth. Each of these domain objects needs access to a small handful of singleton-type helper objects for various purposes.

I was about to implement them using the Java singleton pattern when I remembered that I am already using Spring and I can use Spring to instantiate one of each of these helpers at application startup.

My question is how to I find them from within my domain objects? These are all objects that are created via the "new" operator and are not under the control of Spring.

I'm thinking I could use the "getBean" method if I had my hands on the Spring application context (which I don't) -- but is the performance of this good? I need this stuff to be fast... And how to quickly get the application context?

+1  A: 

In a typical Spring application, the kind of cross-entity logic you're describing is usually implemented in the business service layer (i.e. the Spring-managed singletons), not the domain objects. Domain classes in Spring apps tend to be fairly simple data containers, perhaps with some methods for performing basic operations on the data they encapsulate, but stopping well short of managing complex object graphs outside of themselves. So business service objects manage domain objects, not the other way around.

If you insist on injecting singletons into your domain objects, though, you can achieve this using AspectJ. Spring itself does not support this very well.

Rob H
I hear what you are saying...but it sounds like you are suggesting an anaemic domain model with "transaction script" like service methods. Am I over-stating this? I'm trying hard to avoid a huge isomorphic tree of DAO's to go with my Domain interfaces/classes -- by letting the top level domain objects handle the lower ones. Would like to hear more on why this may be a bad design....
HDave
No huge tree of DAOs required. :-) I usually have one DAO per related group of domain classes, not one per domain class, and each inherits from a base class that has general CRUD methods. But DAOs don't carry business logic, so I think your DAO strategy is orthogonal to the decision as to whether cross-entity business logic is concentrated in domain classes or in service objects. Spring encourages the latter, other frameworks (e.g. Seam) encourage the former. Like everything, there are trade-offs and the best approach probably lies somewhere in the middle.
Rob H
Great explanation....thanks.
HDave
+1  A: 
public class SpringApplicationContextProvider implements ApplicationContextAware {
  public void setApplicationContext(ApplicationContext ctx)
        throws BeansException {
      // Wiring the ApplicationContext into a static method
      SpringApplicationContext.setApplicationContext(ctx);
  }
}

And define SpringApplicationContext as,

public class SpringApplicationContext {
   private static ApplicationContext ctx;

   public static void setApplicationContext(
        ApplicationContext applicationContext) {
      ctx = applicationContext;
   }


   public static ApplicationContext getApplicationContext() {
      return ctx;
   }

   private SpringApplicationContext(){

   }
}

Define SpringApplicationContextProvider as a spring bean in your config file. Now the application context can be accessed using this provider.

chedine
Works great. Seems odd that Spring doesn't have this capability built in, doesn't it?
HDave