Во-первых, очень плохо давать имя, оканчивающееся на Controller, DAO, это очень запутанно, у Controller и DAO все вместе разные цели.
Когда вы добавляете @Transactional
к классу службы или дао, для Spring, чтобы заставить его работать в транзакции, необходимо создать прокси этого класса, своего рода оболочку, в которой он находится перед выполнением прокси-класса (класс в соображение, которое проксируется) метод spring запускает транзакцию и после выполнения в случае, если никакие исключения не завершают транзакцию, это может быть сделано весной через AOP и Annotations. Для описания в коде.
public class OriginalDaoImpl implements OriginalDao extends DaoSupport {
public void save(Object o){
manager.save(o);
}
}
public class ProxyDaoImpl implements OriginalDao {
private OriginalDao originalDaoImpl; //instance of OriginalDaoImpl
public void save(Object o){
try{
transaction.start();
originalDaoImpl.save(o);
transaction.commit();
}catch(Exception e){
transaction.rollback();
}finally{
//clean up code
}
}
}
Как видите, это не точная реализация, а базовый код, как волшебно работает транзакция для вас. Ключевым моментом является наличие интерфейса OriginalDao, который делает эту инъекцию легкой, поскольку OriginalDaoImpl и ProxyDaoImpl реализуют один и тот же интерфейс. Следовательно, их можно поменять местами, т. Е. Прокси, заменяющий оригинал. Этот динамический прокси может быть создан в Java динамическим прокси Java. Теперь вопрос: что, если ваш класс не реализует интерфейс, замена будет сложнее.
Насколько мне известно, одна из библиотек CGLIB помогает в таком сценарии, когда она генерирует динамический подкласс для рассматриваемого класса и в переопределенном методе выполняет магию, как описано выше, вызывая super.save(o)
для делегирования в исходный код.
Теперь к проблеме инъекций.
- Создайте интерфейс и сделайте так, чтобы ваш dao реализовал это, и Spring по умолчанию будет использовать JDK-прокси, как сейчас.
- Добавить атрибут
proxy-target-class="true"
к <tx:annotation-driven transaction-manager="transactionManager"/>
Что касается исключения, то он генерирует, поскольку ожидает, что внедренный компонент будет иметь тип HibernateController, но это не так.
Для справки вы можете обратиться по ссылкам ниже.
- 10.5.6 Использование @ Transactional
- Spring AOP Doc
Надеюсь, это поможет !!!!!.