Announcement Announcement Module
Collapse
No announcement yet.
How to create hierarchical context Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to create hierarchical context

    Hi to everybody,

    I am new to Spring. Right now I am trying to determine the best way to use it.

    What I want to achive is the following:

    1. Every class I have will have a bean factory (ApplicationContext or BeanFactory, doesn't matter, let's keep the discussion abstract). I am not saying that I will create a new factory for each class – I may have one factory for all, layers or indeed a factory for each class.
    When each class tries to get its own factory I need to determine if I should create a new factory or use a parent one. The parent may contain the beans that are used by most of the classes (for example logger definition, some common text resources, like YES/NO button text) and each class may have some special bean which may be needed only by such class or by its children.
    I see that ApplicationContext and BeanFactory have definition for parent, but in order to use the parent I have to know the parent. I need to supply it in the configuration somehow. And somehow I need to know if I have the configuration for the given class. If I have no configuration file the parent must be used (which in turn also may not have the configuration), if I do have a file it must be used.
    The second problem with the ApplicationContext and BeanFactory that if I possibly have one of those for each class I have they will use too much resource. Will they??

    2. When I create a bean from bean factory I will need to provide certain dynamic information (example getLogger(<class name>) factory method has to receive a name of the class that calls it, I can’t configure it for each class – I will need to create a bean definition for each class this way). I need something like getBean(id, Object[] <constructor pareameters>)

    Thank you for your thoughts,
    I hope that I didn't ask stupid questions

  • #2
    You should check the mission statements of Spring:

    Your application code should ''not'' depend on Spring APIs
    If you add a BeanFactory/ApplicationContext to your beans, you are violating the mission statement

    You don`t want your pojo`s to have a reference of any kind to a Spring object. Your pojo`s are created in the application context, but all objects they require can be injected (via constructor or via a setter) in these beans, eg:

    Code:
    interface LoggingService&#123;
        void log&#40;String s&#41;;
    &#125;
    
    class LogginServiceImpl implements LoggingService&#123;
        void log&#40;String s&#41;&#123;... do something ... &#125;
    &#125;
    
    interface FooDao&#123;
         void deleteAllSillyObjects&#40;&#41;;
    &#125;
    
    class FooDaoImpl implements FooDao&#123;
         void deleteAllSillyObjects&#40;&#41;&#123;... delete those bastards ..&#125;
    &#125;
    
    class FooService&#123;
        private FooDao fooDao;
        private LoggingService loggingService;
    
        FooService&#40;FooDao fooDao, LogginService loggingService&#41;&#123;
            this.fooDao = fooDao;
            this.loggingService = logginService;
        &#125;
    
        void sillyMethod1&#40;&#41;&#123; 
             loggingService.log&#40;"silly method1"&#41;;
        &#125;
    
        void sillyMethod2&#40;&#41;&#123;
             fooDao.deleteAllSillyObjects&#40;&#41;;
        &#125;
    &#125;
    And this would be your application context:
    Code:
    <bean id="loggingService" class="LoggingServiceImpl"/>
    
    <bean id="fooDao" class="FooDaoImpl"/>
    
    <bean id="fooService" class="FooService">
    	<constructor-arg>
    		<ref bean="fooDao"/>
    	</constructor-arg>
    	
    	<constructor-arg>
    		<ref bean="loggingService"/>
    	</constructor-arg>
    </bean>
    Now your fooService is created. He received his arguments via a constructor and he realy doesn`t care how he is created. This is the easiest way to set up your beans. As far as your beans are concerned, Spring doesn`t exist.. and that is great because it will make your code more reusable, better testable and not dependant on Spring.


    For a test setup you could create your beans the classic way:

    Code:
    LoggingService loggingService = new MockLoggingService&#40;&#41;;
    FooDao fooDao = new MockFooDao&#40;&#41;;
    FooService fooService = new FooService&#40;fooDao,loggingService&#41;
    If you understand this part of Spring you will see that a new role is emerging: the component configurator/system glue-er. It`s like playing with Lego.. just just fit all the peaces together (maybe creating new ones if one is needed). And the best thing is... you always have enough bricks

    Comment


    • #3
      Anyway I will need to know about Spring somewhere

      In any case, somewhere I will need to write something like:

      appCtx.getBean("myBean")

      I can then pass the result to some class that will not know about Spring. But it looks like selfdeception - my class will be dependant on another class that provides it all of its parameters. It's not coupled, but still...

      Another thing is that I may need a lot of parameters to be passed to my class this way - my class will no be incapsulated well - why does a caller of the class needs to know that I use a logger?

      Comment


      • #4
        Re: Anyway I will need to know about Spring somewhere

        Originally posted by Lock51
        In any case, somewhere I will need to write something like:

        appCtx.getBean("myBean")
        I don`t think you understood my example. In most Spring applications I write, there is not a single appCtx.getBean(...). (Only our Maverick controllers use such a reference) The beans are configured by Spring but they don`t know about Spring.

        Comment


        • #5
          Good example, however I have a similar problem:

          I am using struts with spring. I don't ever write appCtx.getBean(...) either. I rely on the ContextLoaderListener and then have a Context object that wraps an instance of the appCtx. All of my product action code then only ever calls upon this context helper class to getBean information and insulates all my code from the spring framework.

          All of this works great as long as I am in the web container. As soon as I make a buisiness object call, outside of the container (same physical tier) I lose context information.

          How do you get around this?

          Comment

          Working...
          X