第一个疑问就是:每一个set和get方法都依赖于一个具体的实现类,而不是依赖于一个抽象,这正是我们在面向对象的编程中所忌讳的。很明显,这样的依赖注入不能很好地实现扩展。如果我现在的DAO实现的是一个对数据库的访问,我们将不能将它扩展到对XML文件的访问。
大家可能会反驳我,我根本就没想过要更换数据源,因为对于我的项目来说,数据源不太可能会发生变化。好,我再问一句,你的项目的前后台设计编码是分开的吗?果然你的回答还是否定的话,那么在这里对依赖注入模式的使用是毫无作用的,甚至能延缓你的项目开发进度。因为你不得不花费很多时间来做IOC容器的XML配置,这种配置是极为繁琐和容易出错的。
即使你的项目的前后台编码是分开的,但如果在项目的进行中,前后台编码人员容易交流的话,这种情况下对依赖注入的使用也未必有开发人员之间直接交流好。因为对XML配置文件的处理很容易出错,而前后台开发人员之间的直接交流则容易得多。
在这样的一种情况下,前后台的开发人员不容易交流,如他们分布在两个不同的城市里。在这种情况下,使用依赖注入模式才真正的发挥了它的作用。
第二个疑问就是,我们不明白为什么要使用这个接口?这个接口对于我们来说,毫无价值可言。我们完全可以直接使用一个有set和get方法的POJO类。
我们再来看看该接口的实现类:
package …….persistence;
public class IndividualImpl implements IndividualFacade
{
private BasicInfoDAO basicInfoDAO;
private DevelopmentDAO developmentDAO;
private ExperienceDAO experienceDAO;
private ServicesFbDAO servicesFbDAO;
private ServicesGeneralDAO servicesGeneralDAO;
private HrLogDAO hrLogDAO;
private SkillDAO skillDAO;
private OtherDAO otherDAO;
/**
* @return Returns the otherDAO.
*/
public OtherDAO getOtherDAO() {
return otherDAO;
}
/**
* @param otherDAO The otherDAO to set.
*/
public void setOtherDAO(OtherDAO otherDAO) {
this.otherDAO = otherDAO;
}
public BasicInfoDAO getBasicInfoDAO() {
return basicInfoDAO;
}
public void setBasicInfoDAO(BasicInfoDAO basicInfoDAO) {
this.basicInfoDAO = basicInfoDAO;
}
public ServicesGeneralDAO getServicesGeneralDAO() {
return servicesGeneralDAO;
}
public void setServicesGeneralDAO(ServicesGeneralDAO servicesGeneralDAO) {
this.servicesGeneralDAO = servicesGeneralDAO;
}
public DevelopmentDAO getDevelopmentDAO() {
return developmentDAO;
}
public void setDevelopmentDAO(DevelopmentDAO developmentDAO) {
this.developmentDAO = developmentDAO;
}
public ExperienceDAO getExperienceDAO() {
return experienceDAO;
}
public void setExperienceDAO(ExperienceDAO experienceDAO) {
this.experienceDAO = experienceDAO;
}
public ServicesFbDAO getServicesFbDAO() {
return servicesFbDAO;
}
public void setServicesFbDAO(ServicesFbDAO servicesFbDAO) {
this.servicesFbDAO = servicesFbDAO;
}
public HrLogDAO getHrLogDAO()
{
return hrLogDAO;
}
public void setHrLogDAO(HrLogDAO hrLogDAO)
{
this.hrLogDAO = hrLogDAO;
}
public SkillDAO getSkillDAO()
{
return skillDAO;
}
public void setSkillDAO(SkillDAO skillDAO)
{
this.skillDAO = skillDAO;
}
}
看了上面的这个实现类,更加证明了我们上面的说法,即IndividualFacade接口是毫无意义的。我们在IndividualImpl类里去掉IndividualFacade接口的话,对我们的功能和扩展有什么影响吗?
IndividualFacade接口到底对我们有什么作用?
第三个疑问是,IndividualFacade和IndividualImpl在一个包里。假如IndividualFacade真的需要有不同的扩展的话,这两个类在一个包里能够被扩展吗?
下面是一些配置文件:
……
……
从上面的配置示例中,我们可以看到,Spring的配置是比较繁琐的,这样繁琐的配置也是极为容易出错的。所以在我们使用Spring而没有对我们的项目开发有太大的好处时,我们不要勉强使用Spring,因为我们极有可能在这些配置上浪费了大量的时间。
2)
对业务层的依赖注入模式的使用情况
前面提出了使用依赖注入模式的两种情况,即第一是所注入的依赖容易发生改变的情况;第二是依赖和对依赖的使用分开开发的情况。
很显然,在业务层的开发过程中,第一种情况是不大可能发生的,因为相对于表现层,业务层是不大可能发生变化的。在实际情况下,我们多数会遇到对于同一个业务,有不同的表现层。而很少有对于相同的表现层有不同的业务层的情况。
所以对于业务层使用依赖注入模式的原因只有一个,那就是业务层和表现层分开开发,最后他们以插件的形式集成到一起,形成一个完整的系统。
下面我们来看看我们是怎么使用Spring的:
package com.freeborders.psa.service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.freeborders.psa.domain.individual.BasicInfoModel;
import com.freeborders.psa.domain.individual.CertificationModel;
/**
* This interface is used for BasicInfoCertificationManager to implement.
* It defines the actions for the basic info and Certification of an employee.
*/
public interface BasicInfoCertificationService
{
/**
* @param employeeId
* @return int
* @roseuid 42E66C35032C
*/
public int deleteStaffInfo(long employeeId) throws Exception;
/**
* @param employeeId
* @return BasicInfoModel
* @roseuid 42E66C89030D
*/
public BasicInfoModel queryBasicInfo(long employeeId) throws Exception;
/**
* @param basicInfo
* @return int
* @roseuid 42E66CE302FD
*/
public int saveBasicInfo(BasicInfoModel basicInfo) throws Exception;
public int updateBasicInfo(BasicInfoModel basicInfo) throws Exception;
/**
* @param employeeId
* @return CertificationModel
* @roseuid 42E66D6B00DA
*/
public CertificationModel queryServicesFb(long employeeId,int type) throws Exception;
/**
* @param servicesFb
* @return int
* @roseuid 42E66DBD01C5
*/
public int saveServicesFb(CertificationModel servicesFb,int type) throws Exception;
public ArrayList queryNestedDictById(long id) throws Exception;
public Collection queryAllBasic() throws Exception;
public void saveLog(long employeeId) throws Exception;
public String queryLog(long employeeId) throws Exception;
public List queryOrg() throws Exception;
}
首先还是一个接口,前面已经分析过了,业务层不太可能发生变化,在这种情况下,这个接口就显得有点多余。不错,面向对象的编程强调的是对接口编程。但是,对接口的使用也不能滥用。比如,这个接口很难看出它有什么用处。
下面我们来看具体对这个接口的实现:
public class BacicInfoCertificationManager implements BasicInfoCertificationService
{
private HrLogDAO hrLogDAO = null;
private BasicInfoDAO basicInfoDAO = null;
private DictDAO dictDAO = null;
private ServicesGeneralDAO serviceGeneralDAO = null;
public BacicInfoCertificationManager(ApplicationContext applicationContext)
{
this.hrLogDAO = applicationContext.getIndividualFacade().getHrLogDAO();
this.basicInfoDAO = applicationContext.getIndividualFacade().getBasicInfoDAO();
this.dictDAO = applicationContext.getAdminFacade().getDictDAO();
this.serviceGeneralDAO = applicationContext.getIndividualFacade().getServicesGeneralDAO();
}
//list all of the employee info.
public Collection queryAllBasic() throws Exception
{
return this.basicInfoDAO.queryAll();
}
/**
* This function should be kept for extending the system.
*/
public int deleteStaffInfo(long employeeId) throws Exception
{
return 0;
}
public List queryOrg() throws Exception
{
return this.basicInfoDAO.queryOrg();
}
/**
* get the basic info of the employee listed.
*/
public BasicInfoModel queryBasicInfo(long employeeId) throws Exception
{
//get the other basic info
BasicInfoModel model = this.basicInfoDAO.query(employeeId);
//get department
List col = this.basicInfoDAO.queryEmpOrg(employeeId);
if(col.size()>0)
{
model.setDepartmentId(Long.parseLong((String)col.get(0)));