Как мне использовать полиморфизм с Spring Beans?

#spring #polymorphism #javabeans

#spring #полиморфизм #javabeans

Вопрос:

Вот предпосылка того, что я делаю:
— Используйте простой сервлет для получения запросов страниц.
— Получите идентификатор страницы из запроса, чтобы определить, на какой странице я нахожусь.
— Определите контроллеры в XML-конфигурации beans.
— Используйте определение компонента, чтобы определить, какой класс контроллера страницы использовать. — Все эти контроллеры страниц расширяют ядро.Контроллеры.Класс PageController.

Вот что я пытаюсь сделать, но безуспешно. Я пытаюсь загрузить класс контроллера страницы (PersonController, который был определен из компонентов) в переменную PageController. В моем примере кода вы увидите, что я применяю его в классе PageController. Это не работает.

Как мне получить мой объект PersonController из bean factory, используя полиморфизм, в мою переменную?

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- -->
<bean id="home" name="home" class="CORE.Controllers.HomeController" />
<bean id="person" name="person" class="CORE.Controllers.PersonController" />

<!-- Property Management -->
<bean id="propertyEvaluator" class="CORE.Controllers.PropertyManagement.PropertyEvaluator" />
</beans>
  

Класс здесь частично:

 String pageId = "home";
    if (request.getParameter("PID") != null)
    {
        pageId = request.getParameter("PID");
    }

    response.setContentType("text/html; charset=UTF-8"); // Set content type for HTML.
    PrintWriter out = response.getWriter(); // Output goes to the response PrintWriter.
    try
    {
        TransformerFactory tFactory = TransformerFactory.newInstance();
        String ctx = getServletContext().getRealPath("")   FS; //get the real path for xml and xsl files.

        BeanFactory pageFactory = new XmlBeanFactory(new FileSystemResource(ctx "WEB-INF/page-cfg.xml"));
        PageMapping pageMap = (PageMapping) pageFactory.getBean("pageMapping");
        Page page = pageMap.getPageById(pageId);

        BeanFactory controllerFactory = new XmlBeanFactory(new FileSystemResource(ctx "WEB-INF/controller-cfg.xml"));
        PageController controller = (PageController) controllerFactory.getBean(page.getControllerName());
        controller.setRequest(request);
  

Комментарии:

1. Если вы не получаете PersonController , какой тип компонента вы получаете обратно?

2. PageController — это то, что я получаю обратно, потому что я использую его в этом. Я мог бы преобразовать его в PersonController, но я теряю конфигурируемость из Spring Beans. Итак, приведение не сработает. Мне нужно другое решение.

3. Итак, ваша переменная PageController ссылается на объект PersonController — это полиморфизм! Можете ли вы подробнее объяснить, чего вы хотите, поскольку я не вижу, в чем проблема.

4. Следующее — это то, что я изначально пробовал, но оно не компилируется: PageController controller = ControllerFactory.getBean(страница.getControllerName()); // объектом должен быть PersonController , но этот класс распознает ControllerFactory.getBean(страница.getControllerName()) только как универсальный объект, поэтому не компилируется. Мне нужно обдумать это, чтобы попытаться найти лучший способ задать вопрос.

5. из любопытства: почему вы пытаетесь это сделать?

Ответ №1:

Спасибо за обновление. Думаю, теперь я понимаю — вы хотите избежать приведения к PageController .

Заменить

 PageController controller = (PageController)controllerFactory
    .getBean(page.getControllerName());
  

с

 PageController controller = controllerFactory
    .getBean(page.getControllerName(), PageController.class);
  

Spring позволяет параметризовать getBean вызов с типом ожидаемого компонента. С точки зрения внедрения «под капотом», это все еще приведение, и вы получите ClassCastException , если именованный компонент не соответствует запрошенному типу, но, по крайней мере, теперь компилятор обрабатывает это с помощью generics.

Ответ №2:

Весной, если мы используем JDK proxy (как исправлено @mdma ниже), мы не можем привести объект к конкретному экземпляру класса, мы можем привести его только к экземпляру интерфейса in. В этом случае вам нужно изменить PageController на интерфейс и создать для него реализацию с именем PageControllerImpl и объявить ее в вас controller-cfg.xml .

Если используется CGLIB, ваш код может работать нормально.

Комментарии:

1. Хотя это верно, если вы используете AOP (и прокси JDK), обычно это не так. Контекст может создавать экземпляры именно тех классов, которые вы указываете, и предоставлять их «как есть».