Скрытые возможности фреймворка Spring?
После просмотра множества скрытых возможностей языка программирования, я хотел бы узнать скрытые возможности среды "де-факто" Spring. Как вы знаете, в документации Spring скрыты многие функции, и было бы неплохо поделиться ею.
А вы: какую скрытую особенность Spring Framework вы знаете?
6 ответов
Spring имеет мощный встроенный класс StringUtils
Обратите внимание на следующий массив, содержащий набор идентификаторов
String [] idArray = new String [] {"0", "1", "2", "0", "5", "2"}
И вы хотите удалить дубликаты ссылок. Просто сделай это
idArray = StringUtils.removeDuplicateStrings(idArray);
Теперь idArray будет содержать {"0", "1", "2", "5"}.
И многое другое.
Можно ли использовать класс Controller без объявления их в файле контекста веб-приложения?
Да, просто поместите @Component в его объявлении (@Controller не работает должным образом)
package br.com.spring.view.controller
@Component
public class PlayerController extends MultiActionController {
private Service service;
@Autowired
public PlayerController(InternalPathMethodNameResolver ipmnr, Service service) {
this.service = service;
setMethodNameResolver(ipmnr);
}
// mapped to /player/add
public ModelAndView add(...) {}
// mapped to /player/remove
public ModelAndView remove(...) {}
// mapped to /player/list
public ModelAndView list(...) {}
}
Итак, в файле контекста веб-приложения укажите
<beans ...>
<context:component-scan base-package="br.com.spring.view"/>
<context:annotation-config/>
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
<property name="order" value="0"/>
<property name="caseSensitive" value="true"/>
</bean>
<bean class="org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver"/>
</beans>
Ничего больше
Валидация в динамических формах?
Используйте следующее
public class Team {
private List<Player> playerList;
}
Так в Команде валидатор поставь
@Component
public class TeamValidator implements Validator {
private PlayerValidator playerValidator;
@Autowired
public TeamValidator(PlayerValidator playerValidator) {
this.playerValidator = playerValidator;
}
public boolean supports(Class clazz) {
return clazz.isAssignableFrom(Team.class);
}
public void validate(Object command, Errors errors) {
Team team = (Team) command;
// do Team validation
int index = 0;
for(Player player: team.getPlayerList()) {
// Notice code just bellow
errors.pushNestedPath("playerList[" + index++ + "]");
ValidationUtils.invokeValidator(playerValidator, player, errors);
errors.popNestedPath();
}
}
}
Наследование в веб-формах?
Используйте ServlerRequestDataBinder вместе со скрытым флагом формы
public class Command {
private Parent parent;
}
public class Child extends Parent { ... }
public class AnotherChild extends Parent { ... }
И в вашем контроллере сделайте следующее
public class MyController extends MultiActionController {
public ModelAndView action(HttpServletRequest request, HttpServletResponse response, Object command) {
Command command = (Command) command;
// hidden form flag
String parentChildType = ServletRequestUtils.getRequiredStringParameter(request, "parentChildType");
// getApplicationContext().getBean(parentChildType) retrieves a Parent object from a application context file
ServletRequestDataBinder binder =
new ServletRequestDataBinder(getApplicationContext().getBean(parentChildType));
// populates Parent child object
binder.bind(request);
command.setParent((Parent) binder.getTarget());
}
Spring имеет встроенный класс сканера ClassPathScanningCandidateComponentProvider. Вы можете использовать его, например, для поиска аннотаций.
ClassPathScanningCandidateComponentProvider scanner =
new ClassPathScanningCandidateComponentProvider(<DO_YOU_WANT_TO_USE_DEFAULT_FILTER>);
scanner.addIncludeFilter(new AnnotationTypeFilter(<TYPE_YOUR_ANNOTATION_HERE>.class));
for (BeanDefinition bd : scanner.findCandidateComponents(<TYPE_YOUR_BASE_PACKAGE_HERE>))
System.out.println(bd.getBeanClassName());
Spring имеет полезный класс org.springframework.util.FileCopyUtils. Вы можете скопировать загруженный файл, используя
public ModelAndView action(...) throws Exception {
Command command = (Command) command;
MultiPartFile uploadedFile = command.getFile();
FileCopyUtils.copy(uploadedFile.getBytes(), new File("destination"));
Если вы используете контроллер на основе аннотаций (Spring 2.5+) или обычный контроллер MVC Spring, вы можете использовать WebBindingInitializer для регистрации глобальных редакторов свойств. Что-то вроде
public class GlobalBindingInitializer implements WebBindingInitializer {
public void initBinder(WebDataBinder binder, WebRequest request) {
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("dd/MM/yyyy", true);
}
}
Итак, в вашем файле контекста веб-приложения объявите
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="webBindingInitializer">
<bean class="GlobalBindingInitializer"/>
</property>
</bean>
Таким образом, любой контроллер на основе аннотаций может использовать любой редактор свойств, объявленный в GlobalBindingInitializer.
И так далее...
Spring можно использовать в качестве замены шины событий, так как ApplicationContext
также ApplicationEventPublisher
Ссылочная реализация Spring находится в SimpleApplicationEventMulticaster
, который может дополнительно использовать пул потоков для асинхронного распределения событий.
Одним из них является использование прокси классов на основе CGLib для Spring AOP. Это также может быть сделано через динамические прокси Java, но по умолчанию используется CGLib. Так что не удивляйтесь, если вы увидите CGLib в вашей трассировке стека.
Другое использование АОП для DI. Да, это все АОП везде, без вашего ведома. Приятно знать, что ваш код основан на AOP, даже если вы используете Spring только для целей DI.
В отличие от типичного проприетарного программного обеспечения, исходный код для Spring свободно доступен для всех, кто хочет его скачать.
Поэтому Spring не имеет скрытых возможностей. Это просто особенности, которые вы еще не видели... пока.
Лучший способ найти какие-либо скрытые функции в Spring - просто взглянуть на исходный код.
Трудно сказать, что является скрытой функцией, хотя Spring очень гибок с аннотациями, AspectJ и использованием DI.