Spring 3 @controller не может внедрить служебный объект, который имеет @Transactional - PullRequest
4 голосов
/ 10 февраля 2011

Я использую Spring 3 MVC, у меня проблема с введением объектов.Я создал объект контроллера с @Controller.И я создал объект службы с помощью объекта @Service.Я ввел сервисный объект в контроллер с помощью AutoWire.И я создал объект DAO, и вставил в объект службы, и протестировал приложение, оно работает нормально.Затем я поставил @Transactional на DAO, тогда тоже все работало нормально.Но когда я ставлю @Transactional на сервисный объект, это дает мне проблему.Во время развертывания на контроллере он говорит: «

Сбой инициализации контекста: org.springframework.beans.factory.BeanCreationException: Ошибка при создании бина с именем« loginController »: сбой внедрения зависимостей с автопроводкой»; вложенным исключением является org.springframework.beans.factory.BeanCreationException: Не удалось автоматически связать метод: public void com.erudicus.controller.LoginController.setLoginService (com.erudicus.model.service.LoginServiceImpl): несоответствие типа аргумента ".

Вот код контроллера

@Controller
public class LoginController {
     private static Logger LOG = Logger.getLogger(LoginController.class);

    private LoginServiceImpl loginService = null;


    public LoginServiceImpl getLoginService() {
        return loginService;
    }

    @Autowired
    public void setLoginService(LoginServiceImpl loginService) {
                this.loginService = loginService;
    }

    @RequestMapping(value="/login" , method= RequestMethod.GET)
    public String login(Model model) {
        model.addAttribute(new Login());
            return "login";
    }

    @RequestMapping(value="/loginDetails", method=RequestMethod.POST)
    public ModelAndView create(@Valid Login login, BindingResult result) {
      }
}

Сервисный объект

@Service
public class LoginServiceImpl implements LoginService {

    private LoginDao loginDao = null;


    public LoginDao getLoginDao() {
        return loginDao;
    }

    @Autowired
    public void setLoginDao(LoginDao loginDao) {
        this.loginDao = loginDao;
    }

    @Transactional(readOnly = true, propagation = Propagation.REQUIRED)
    public Login getUserDetails(String userId) {
           return getLoginDao().getUserDetails(userId);
    }
}

Дао

@Service
@Transactional(propagation = Propagation.MANDATORY)
public class LoginDaoImpl extends SqlSessionDaoSupport implements LoginDao {

    @Transactional(readOnly = true, propagation = Propagation.MANDATORY)
    public Login getUserDetails(String userId) {
    }
}

В Конфигурации я указал

<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
    <!-- enable autowire -->
    <!-- enable transaction demarcation with annotations -->
    <tx:annotation-driven transaction-manager="txManager"/>
 <context:annotation-config/>

Любой может помочь, пожалуйста

1 Ответ

11 голосов
/ 10 февраля 2011

Определите поле как интерфейс, а не конкретный класс. (То есть UserService вместо UserServiceImpl). Вы можете добавить аннотацию @Transactional для конкретного класса - она ​​будет работать.

Проблема в том, что по умолчанию в Spring используются прокси JDK (java.lang.reflect.Proxy), которые являются прокси только для интерфейса. Ваш конкретный класс затем используется обработчиком вызова, но вы не можете привести его к нему.

Если интерфейса нет, Spring использует другой метод - CGLIB, который создает подкласс целевого класса для создания прокси.

Вы можете использовать <aop:scoped-proxy />, чтобы настроить прокси-страгегию (proxy-target-class) для каждого бина.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...