【发布时间】:2015-08-11 13:52:49
【问题描述】:
这是一个关于Spring用于业务对象的问题,以及它们被注入到需要它们的类后如何存储。
在典型的 Spring 设置中,您可能有如下业务对象:
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
}
上面的 bean XML 条目可能如下所示:
<bean id="baseDAO" class="app.dao.base.BaseDAO" abstract="true">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="courseDAO" class="app.dao.impl.CourseDAO"
parent="baseDAO">
</bean>
<bean id="studentDAO" class="app.dao.impl.StudentDAO"
parent="baseDAO">
</bean>
<bean id="courseAssignDAO" class="app.dao.impl.CourseAssignDAO"
parent="baseDAO">
</bean>
<bean id="maintainStudent" class="app.service.impl.MaintainStudent">
<property name="courseDAO" ref="courseDAO" />
<property name="studentDAO" ref="courseAssignDAO" />
<property name="courseAssignDAO" ref="studentDAO" />
</bean>
我的问题是,可以将注入的 bean 存储在 HashMap 中而不是单独的接口变量中吗?我问这个问题是因为我正在为我支持的应用程序进行移植项目,并且我正在尝试用 Spring 替换应用程序的 EJB / JDBC 事务架构。我使用 Struts2 和 Spring 作为应用程序的新架构。我在这个项目中使用 Spring 主要是为了它的数据库事务功能。现有应用程序使用工厂类来实例化所有内容,我想出了一种方法,通过将 bean 存储在 HashMap 中,使用工厂类将架构转换为依赖注入。
以下是使用我的HashMap 存储bean 方法的相同业务对象的示例:
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
}
BaseBusinessObj 类:
package app.base;
public class BaseBusinessObj implements org.springframework.beans.factory.DisposableBean
{
private Map<String, Object> springBeans = new HashMap<String, Object>();
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();
}
}
修改后的 bean XML 条目:
<bean id="baseBusinessObj" class="app.base.BaseBusinessObj" abstract="true">
</bean>
<bean id="baseDAO" class="app.dao.base.BaseDAO" abstract="true"
parent="baseBusinessObj">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="courseDAO" class="app.dao.fact.CourseDAOFactory"
parent="baseDAO">
</bean>
<bean id="studentDAO" class="app.dao.fact.StudentDAOFactory"
parent="baseDAO">
</bean>
<bean id="courseAssignDAO" class="app.dao.fact.CourseAssignDAOFactory"
parent="baseDAO">
</bean>
<bean id="maintainStudent" class="app.service.fact.MaintainStudentFactory"
parent="baseBusinessObj">
<property name="courseDAO" ref="courseDAO" />
<property name="studentDAO" ref="courseAssignDAO" />
<property name="courseAssignDAO" ref="studentDAO" />
</bean>
现在提供注入 bean 而不是创建新实例的示例转换工厂类:
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;
}
}
我上面的架构所做的是提供以传统的非 DI 风格编写代码的能力,允许开发人员明确地“请求”所需的对象。此请求与自己创建(实例化)对象类似。在我的架构中,“请求一个 Bean”已经取代了“创建一个新实例”,因此工厂类语句可以留在代码中,同时使代码与依赖注入架构一起工作。我将创建一个代码生成器,它会自动为每个需要它们的类生成所需的注入器方法。
我已经测试了上述架构并且它可以工作。事务按预期提交和回滚。
我只是想知道我创建的这个架构是否仍然允许 Spring 按设计运行。
使用这种架构,在事务完成后,我的所有 bean 是否仍然能够被 Spring 销毁?还是会因为HashMap的存储思路而在内存中出现挂件?
让我知道你的想法。感谢您抽出宝贵时间阅读本文。
【问题讨论】:
-
在map中存储bean有什么意义?如果你不喜欢注入变量,那么你可以从 spring 上下文中获取所需的 bean。
-
@AleksandrM 从 ApplicationContext 调用 getBean 方法来获取所有 bean 会中断事务吗?还是事务仍会按预期传播、提交和回滚?
标签: java spring dependency-injection