【问题标题】:Spring 3 Service Dao layers with abstract class question带有抽象类问题的 Spring 3 Service Dao 层
【发布时间】:2011-10-17 13:59:52
【问题描述】:

我正在尝试在我的服务层中实现一个通用抽象类。我已经在我的 dao 层中使用了类似的模式,它工作正常。我在 Spring in Practice v8 电子书中找到了一个工作示例。我想知道是否有办法自动装配以下工作代码。 (代码有效,但在使用类中的任何其他方法之前,我必须调用我的辅助方法“setDao”)

测试类:

    public class App {


    public static void main(String[] args) {
        ApplicationContext appContext = new ClassPathXmlApplicationContext("classpath:/applicationContext.xml");

        MyService service = (MyService)appContext.getBean("myService");

        service.setDao();

        Heading detail = new Heading();
        detail.setName("hello");

        service.save(detail);

        Heading dos = service.findById(Long.valueOf(1));
        System.out.println(dos);
    }
}

MyServiceImpl 类

    @Service("myService")
public class MyServiceImpl extends AbstractServiceImpl<Heading> implements HeadingService {

    @Autowired
    private HeadingDao headingDao;

    public void setHeadingDao(HeadingDao headingDao) {
        this.headingDao = headingDao;
    }

    public void setDao() {
        super.setDao(this.headingDao);
    }

}

我的服务接口

    public interface HeadingService extends AbstractService<Heading> {
    public void setDao();
}

AbstractServiceImpl 类

    @Service
public abstract class AbstractServiceImpl<T extends Object> implements AbstractService<T> {

    private AbstractDao<T> dao;

    public void setDao(AbstractDao<T> dao) {
        this.dao = dao;
    }

    public void save(T t) {
        dao.save(t);
    }

    public T findById(Long id) {
        return (T)dao.findById(id);
    }

    public List<T> findAll() {
        return dao.findAll();
    }

    public void update(T t) {
        dao.update(t);
    }

    public void delete(T t) {
        dao.delete(t);
    }

    public long count() {
        return dao.count();
    }

}

抽象服务接口

    public interface AbstractService<T extends Object> {

    public void save(T t);
    public T findById(Long id);
    public List<T> findAll();
    public void update(T t);
    public void delete(T t);
    public long count();

}

【问题讨论】:

    标签: java spring design-patterns abstract-class service-layer


    【解决方案1】:

    不必调用方法 (setDao()) 以允许您的子类将 DAO 引用传递给您的超类,为什么要反转方向并强制子类将 DAO 提供给超类?

    例如:

    public abstract class AbstractServiceImpl<T extends Object> implements AbstractService<T> {
        private AbstractDao<T> dao;
    
        abstract AbstractDao<T> getDao();
    
        public void save(T t) {
            getDao().save(t);
        }
    }
    
    public class FooServiceImpl extends AbstractServiceImpl<Foo> {
         @Autowired
         private FooDao fooDao;
    
         @Overrides
         public AbstractDao<Foo> getDao() {
             return fooDao;
         }
    }
    

    无需在外部调用方法来启动引用传递链。

    【讨论】:

    • 顺便说一句,关于您的 AbstractService - 似乎您的通用 DAO 和 Service 接口具有几乎相同的方法定义。这有什么意义 - 如果大量的服务方法只是调用 DAO 方法,为什么还要费心从 DAO 中建立一个单独的服务层?每个使用 AbstractService 的类是否真的需要能够访问 count()findAll() 方法?我建议考虑减少这个抽象类中可用的服务层方法的大小,并且只编写真正需要的方法——应该减少很多代码。
    • 谢谢。这确实更有意义。
    【解决方案2】:

    尝试让您的 MyServiceImpl 实现 InitializingBean,并将您的 setDao() 方法更改为 afterPropertiesSet()。它会在框架调用完 setter 后自动被调用。

    或者,(更简单),只需在您的 setHeaderDao(...) 方法中调用 setDao()。

    【讨论】:

    • 我尝试了您的第二个建议,但会引发空指针异常。我现在将尝试您的第一个建议。我试图为实现类找到一种干净的 Spring 方式来声明要使用的 dao,然后在具有通用 crud 操作的抽象类中使用它。
    • 实现 InitializingBean 工作,它让我在我的测试类中删除调用。我认为这应该有效。您以前使用过与此类似的模式吗?我只是认为在服务之间提取类似的代码是有意义的。
    • 通用 dao 没做过,但有道理。 InitializingBean 是在框架注入所有值之后执行代码的标准 spring 方式。很高兴它对你有用。
    【解决方案3】:

    将spring框架版本升级到4,问题就解决了。
    检查this页面。

    【讨论】:

    • 您应该将链接中的“关键点”放入您的答案中,并将链接用作参考。另外,解释为什么某些东西会起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-20
    • 1970-01-01
    • 2016-11-28
    • 1970-01-01
    • 1970-01-01
    • 2016-05-06
    相关资源
    最近更新 更多