Spring 3 Слои Service 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);
    }

}

Интерфейс MyService

    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();

}

person blong824    schedule 01.08.2011    source источник


Ответы (3)


Вместо того, чтобы вызывать метод (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;
     }
}

Нет необходимости вызывать метод извне, чтобы запустить цепочку передачи ссылок.

person matt b    schedule 01.08.2011
comment
Кстати, о вашем AbstractService - кажется, что ваши общие интерфейсы DAO и Service имеют почти идентичные определения методов. В чем смысл этого — зачем создавать отдельный уровень службы от DAO, если большое количество методов службы просто вызывает метод DAO? Действительно ли каждый класс, использующий AbstractService, должен иметь доступ к методам count() или findAll()? Я бы предложил рассмотреть возможность уменьшения размера методов сервисного уровня, доступных в этом абстрактном классе, и писать только те методы, которые действительно необходимы, что должно сократить объем кода. - person matt b; 01.08.2011
comment
Спасибо. Это имеет больше смысла. - person blong824; 01.08.2011

Попробуйте реализовать в MyServiceImpl InitializingBean и измените метод setDao() на afterPropertiesSet(). Он будет автоматически вызываться после того, как фреймворк завершит вызов сеттеров.

Или (что еще проще) просто вызовите setDao() в вашем методе setHeaderDao(...).

person Kevin    schedule 01.08.2011
comment
Я попробовал ваше второе предложение, и это вызывает исключение нулевого указателя. Сейчас попробую ваше первое предложение. Я пытался найти чистый способ Spring для класса реализации, чтобы объявить, какой дао использовать, а затем использовать это в абстрактном классе с общими грубыми операциями. - person blong824; 01.08.2011
comment
Реализация InitializingBean сработала, и это позволило мне удалить вызов в моем тестовом классе. Я думаю, это должно сработать. Использовали ли вы шаблон, похожий на этот, раньше? Я просто подумал, что имеет смысл вытащить аналогичный код между сервисами. - person blong824; 01.08.2011
comment
Я не делал общий дао, но это имеет смысл. InitializingBean — это стандартный пружинный способ выполнения кода после того, как фреймворк внедрил все значения. Рад, что это сработало для вас. - person Kevin; 01.08.2011

Обновите версию Spring Framework до 4, и проблема будет решена.
проверьте это страница.

person Ali Sadeghi    schedule 18.12.2015
comment
Вы должны поместить ключевые моменты из ссылки в свой ответ и просто использовать ссылку в качестве ссылки. Кроме того, объясните, почему что-то будет работать. - person ; 18.12.2015