#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), обычно это не так. Контекст может создавать экземпляры именно тех классов, которые вы указываете, и предоставлять их «как есть».