title: Storing injected Spring Beans in a HashMap
body: <p>This is a question about the use of Spring for business objects and how they are stored after being injected into classes that need them.</p>
  
  <p>In a typical Spring setup, you might have a business object as follows:</p>
  
  <pre><code>package app.service.impl;
  
  public class MaintainStudent implements app.service.intf.MaintainStudent
  {
      protected app.dao.intf.CourseDAO courseDAO;
      protected app.dao.intf.StudentDAO studentDAO;
      protected app.dao.intf.CourseAssignDAO courseAssignDAO;
  
      //injection methods here
      public void setCourseDAO(app.dao.intf.CourseDAO courseDAO)
      {
          this.courseDAO = courseDAO;
      }
  
      public void setStudentDAO(app.dao.intf.StudentDAO studentDAO)
      {
          this.studentDAO = studentDAO;
      }
  
      public void setCourseAssignDAO(app.dao.intf.CourseAssignDAO courseAssignDAO)
      {
          this.courseAssignDAO = courseAssignDAO;
      }
      //end injection methods
  
      //example business method
      @Override
      @Transactional(rollbackFor={Exception.class})
      public void assignCourse(StudentKey studenKey, CourseKey courseKey)
      {
          courseAssignDAO.assignCourse(studentKey, courseKey);
      }
  
      //rest of the class here
  }
  </code></pre>
  
  <p>The bean XML entries for the above might look like this:</p>
  
  <pre><code>&lt;bean id="baseDAO" class="app.dao.base.BaseDAO" abstract="true"&gt;
      &lt;property name="dataSource" ref="dataSource" /&gt;
  &lt;/bean&gt;
  
  &lt;bean id="courseDAO" class="app.dao.impl.CourseDAO"
      parent="baseDAO"&gt;
  &lt;/bean&gt;
  
  &lt;bean id="studentDAO" class="app.dao.impl.StudentDAO"
      parent="baseDAO"&gt;
  &lt;/bean&gt;    
  
  &lt;bean id="courseAssignDAO" class="app.dao.impl.CourseAssignDAO"
      parent="baseDAO"&gt;
  &lt;/bean&gt;
  
  &lt;bean id="maintainStudent" class="app.service.impl.MaintainStudent"&gt;
      &lt;property name="courseDAO" ref="courseDAO" /&gt;
      &lt;property name="studentDAO" ref="courseAssignDAO" /&gt;
      &lt;property name="courseAssignDAO" ref="studentDAO" /&gt;
  &lt;/bean&gt;
  </code></pre>
  
  <p>My question is, is it ok to store the injected beans in a <code>HashMap</code> instead of in individual interface variables?  I ask this question because I am working on a porting project for an applicaion I support and I am trying to replace the application's EJB / JDBC transaction architecture with Spring.  I am using Struts2 and Spring as the new architecture for the application.  I am using Spring in this project primarily for its Database Transaction capabilities.  The existing application uses factory classes to instantiate everything, and I have come up with a way of converting the architecture to Dependency Injection using the factory classes by storing the beans in a <code>HashMap</code>.</p>
  
  <p>Below is an example of the same business object using my <code>HashMap</code> method of storing the beans:</p>
  
  <pre><code>package app.service.impl;
  
  public class MaintainStudent extends app.base.BaseBusinessObj
      implements app.service.intf.MaintainStudent
  { 
      //injection methods here
      public void setCourseDAO(app.dao.intf.CourseDAO courseDAO)
      {
          this.springBeans.add(courseDAO.getClass().getName(), courseDAO);
      }
  
      public void setStudentDAO(app.dao.intf.StudentDAO studentDAO)
      {
          this.springBeans.add(studentDAO.getClass().getName(), studentDAO);
      }
  
      public void setCourseAssignDAO(app.dao.intf.CourseAssignDAO courseAssignDAO)
      {
          this.springBeans.add(courseAssignDAO.getClass().getName(), courseAssignDAO);
      }
      //end injection methods
  
      //example business method
      @Override
      @Transactional(rollbackFor={Exception.class})
      public void assignCourse(StudentKey studenKey, CourseKey courseKey)
      {
          app.dao.intf.CourseAssignDAO courseAssignDAO =
              app.dao.fact.CourseAssignDAOFactory.requestBean(this);
  
          courseAssignDAO.assignCourse(studentKey, courseKey);
      }
  
      //rest of the class here
  }
  </code></pre>
  
  <p>BaseBusinessObj class:</p>
  
  <pre><code>package app.base;    
  
  public class BaseBusinessObj implements org.springframework.beans.factory.DisposableBean
  {
      private Map&lt;String, Object&gt; springBeans = new HashMap&lt;String, Object&gt;();
  
      public void addBean(String className, Object bean)
      {
          this.springBeans.put(className, bean);
      }
  
      public Object getBean(String className)
      {
          return this.springBeans.get(className);
      }
  
      @Override
      public void destroy() throws Exception
      {
          this.springBeans.clear();
      }
  }
  </code></pre>
  
  <p>Modified bean XML entries:</p>
  
  <pre><code>&lt;bean id="baseBusinessObj" class="app.base.BaseBusinessObj" abstract="true"&gt;
  &lt;/bean&gt;
  
  &lt;bean id="baseDAO" class="app.dao.base.BaseDAO" abstract="true"
      parent="baseBusinessObj"&gt;
      &lt;property name="dataSource" ref="dataSource" /&gt;
  &lt;/bean&gt;
  
  &lt;bean id="courseDAO" class="app.dao.fact.CourseDAOFactory"
      parent="baseDAO"&gt;
  &lt;/bean&gt;
  
  &lt;bean id="studentDAO" class="app.dao.fact.StudentDAOFactory"
      parent="baseDAO"&gt;
  &lt;/bean&gt;
  
  &lt;bean id="courseAssignDAO" class="app.dao.fact.CourseAssignDAOFactory"
      parent="baseDAO"&gt;
  &lt;/bean&gt;
  
  &lt;bean id="maintainStudent" class="app.service.fact.MaintainStudentFactory"
      parent="baseBusinessObj"&gt;
      &lt;property name="courseDAO" ref="courseDAO" /&gt;
      &lt;property name="studentDAO" ref="courseAssignDAO" /&gt;
      &lt;property name="courseAssignDAO" ref="studentDAO" /&gt;
  &lt;/bean&gt;
  </code></pre>
  
  <p>Sample converted factory class that now serves up an injected bean instead of creating a new instance:</p>
  
  <pre><code>package app.dao.fact;
  
  public class CourseAssignDAOFactory extends app.dao.impl.CourseAssignDAO
  {
      protected CourseAssignDAOFactory()
      {
          super();
      }
  
      //method formerly called "newInstance()"
      public static app.dao.intf.CourseAssignDAO requestBean(app.base.BaseBusinessObj requester)
      {
          app.dao.intf.CourseAssignDAO result;
          Object requestedBean = requester.getBean(CourseAssignDAOFactory.class.getName());
          result = (app.dao.intf.CourseAssignDAO)requestedBean;
  
          return result;
      }
  }
  </code></pre>
  
  <p>What my architecture above does is provide the capability of writing code in a traditional non-DI style that allows the developer to explicitly "request" needed objects.  This requesting is a similar activity to creating (instantiating) objects yourself.  In my architecture, 'Requesting a Bean' has replaced 'Creating a New Instance' so that the Factory Class statements can be left in the code while making the code work with Dependency Injection architecture.  I'm going to create a code generator that will automatically generate the required injector methods into every class that needs them.</p>
  
  <p>I have tested the above architecture and it works.  Transactions commit and rollback when expected.</p>
  
  <p>I'm just wondering if this architecture I have created will still allow Spring to behave as designed.</p>
  
  <p>With this architecture, will all of my beans still be able to be destroyed by Spring after a transaction is complete?  Or will there be hanging objects in memory because of the <code>HashMap</code> storage idea?</p>
  
  <p>Let me know what you think.  Thanks for taking the time to read this.</p>