这是一个关于将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样式编写代码的功能,允许开发人员明确“请求”所需的对象。此请求是与自己创建(实例化)对象类似的活动。在我的架构中,'Requesting a Bean'已经取代了'创建新实例',因此Factory类语句可以保留在代码中,同时使代码可以使用依赖注入体系结构。我将创建一个代码生成器,它将自动生成所需的注入器方法到每个需要它们的类中。
我已经测试了上面的架构并且它可以工作。事务在预期时提交和回滚。
我只是想知道我创建的这个架构是否仍然允许Spring按照设计行事。
使用这种架构,在事务完成后,我的所有bean仍然可以被Spring销毁吗?或者由于HashMap
存储想法会在内存中挂起对象吗?
让我知道你的想法。感谢您花时间阅读本文。
答案 0 :(得分:0)
您可以使用Provider<Type>
替换工厂并改为注入:
public class CourseAssignDaoUser {
@Autowired
private Provider<CourseAssignDao> factory;
void useDao() {
CourseAssignDao dao = factory.get();
// ...
}
}
甚至直接注入值:
public class CourseAssignDaoUser {
@Autowired
private CourseAssignDao dao;
void useDao() {
// ...
}
}
如果由于某种原因无法实现,则可以使用Spring上下文 使用地图:
public class CourseAssignDAOFactory {
public static CourseAssignDAO requestBean(ApplicationContext context) {
return context.getBean(CourseAssignDao.class);
}
}
但是使用@Autowired
有或没有Provider
绝对是最好的
溶液