Этот небольшой список вопросов даст вам понимание самых важных концепций Spring, а так же поможет подготовится к собеседованию
Если вы понимаете как работает Component Scan, то вы понимаете Spring
Первый шаг для описания Spring Beans это добавление аннотации — @Component
, или @Service
, или @Repository
.
Однако, Spring ничего не знает об этих бинах, если он не знает где искать их. То, что скажет Spring где искать эти бины и называется Component Scan. В @ComponentScan вы указываете пакеты, которые должны сканироваться.
Spring будет искать бины не только в пакетах для сканирования, но и в их подпакетах.
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@SpringBootApplication определяет автоматическое сканирование пакета, где находится класс Application
Всё будет в порядке, ваш код целиком находится в указанном пакете или его подпакетах.
Однако, если необходимый вам компонент находится в другом пакете, вы должны использовать дополнительно аннотацию @ComponentScan, где перечислите все дополнительные пакеты для сканирования
@Component
и @ComponentScan
предназначены для разных целей
@Component
помечает класс в качестве кандидата для создания Spring бина.
@ComponentScan
указывает где Spring искать классы, помеченные аннотацией @Component
или его производной
В классах конфигурации Spring, @Bean
используется для определения компонентов с кастомной логикой.
@Bean
используется в конфигурационных классах Spring. Он используется для непосредственного создания бина.
@Component
используется со всеми классами, которыми должен управлять Spring. Когда Spring видит класс с @Component
, Spring определяет этот класс как кандидата для создания bean.
Все они определяют бины Spring. Однако между ними всё же есть разница.
@Component
— универсальный компонент
@Repository
— компонент, который предназначен для хранения, извлечения и поиска. Как правило, используется для работы с базами данных.
@Service
— фасад для некоторой бизнес логики
Пользовательские аннотации, производные от @Component
, могут добавлять специальную логику в бинах.
Например, бины, получившиеся при помощи @Repository
, дополнительно имеют обработку для JDBC Exception
Да. конечно.
Если @Component
является универсальным стереотипом для любого Spring компонента, то @Service
в настоящее время является его псевдонимом. Однако, в официальной документации Spring рекомендуется использовать именно @Service
для бизнес логики. Вполне возможно, что в будущих версиях фреймворка, для данного стереотипа добавится дополнительная семантика, и его бины станут обладать дополнительной логикой.
web.xml — Метаданные и конфигурация любого веб-приложения, совместимого с Java EE. Java EE стандарт для веб-приложений.
servlet.xml — файл конфигурации, специфичный для Spring Framework.
Предпочитаю аннотации, если кодовая база хорошо описывается такими элементами, как @Service, @Component, @Autowired
Однако когда дело доходит до конфигурации, у меня нет каких-либо предпочтений. Я бы оставил этот вопрос команде.
Да, конечно.
@Autowired может использоваться вместе с конструкторами, сеттерами или любым другими методами. Когда Spring находит @Autowired на методе, Spring автоматически вызовет этот метод, после создания экземпляра бина. В качестве аргументов, будут подобраны подходящие объекты из контекста Spring.
Сквозная Функциональность — функциональность, которая может потребоваться вам на нескольких различных уровнях — логирование, управление производительностью, безопасность и т.д.
АОП — один из подходов к реализации данной проблемы
IOC — инверсия управления. Вместо ручного внедрения зависимостей, фреймворк забирает ответственность за это.
ApplicationContext — реализация IOC спрингом.
Bean Factory — это базовая версия IOC контейнера
Application Context также включает дополнительные функции, которые обычно нужны для разработки корпоративных приложений
classPathXmlApplicationContext — если вы хотите инициализировать контекст Spring при помощи xml
annotationConfigApplicationContext — если вы хотите инициализировать контекст Spring при помощи конфигурационного класса java
Метод, помеченный аннотацией @Around
, должен возвращать значение, которое он (метод) получил из joinpoint.proceed()
@Around("trackTimeAnnotation()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
long startTime = System.currentTimeMillis();
Object retVal = joinPoint.proceed();
long timeTaken = System.currentTimeMillis() - startTime;
logger.info("Time taken by {} is equal to {}",joinPoint, timeTaken);
return retVal;
}
Если есть бин, который вы предпочитаете большую часть времени по сравнению с другими, то используйте @Primary
, и используйте @Qualifier
для нестандартных сценариев.
Если все бины имеют одинаковый приоритет, мы всегда будем использовать @Qualifier
Если бин надо выбрать во время исполнения программы, то эти аннотации вам не подойдут. Вам надо в конфигурационном классе создать метод, пометить его аннотацией @Bean
, и вернуть им требуемый бин.
На мой взгляд это Functional Web Framework, Kotlin и и поддержка реактивного программирования.
Web Container и EJB Containers являются частью приложения/веб-сервера, таких как Tomcat, Websphere, Weblogic. Они добавляют свою дополнительную функциональность к ним. Java EE определяет контракт для веб-приложений, эти контейнеры являются реализацией этих контрактов.
Spring контейнер может являться частью любого приложения, которое вы делаете на java. Spring может работать внутри веб-контейнера, ejb контейнера или даже без них.
Рассмотрим пример:
interface GreetingService {
public String sayHello();
}
И два компонента
@Component(value="real")
class RealGreetingService implements GreetingService {
public String sayHello() {
return "I'm real";
}
}
@Component(value="mock")
class MockGreetingService implements GreetingService {
public String sayHello() {
return "I'm mock";
}
}
Тогда в application.properties добавим свойство
application.greeting: real
Воспользуемся данным решением:
@RestController
public class WelcomeController {
@Resource(name="${application.greeting}")
private GreeterService service1;
}
Spring 5.0 и Spring Boot 2.0 поддерживают Java 8 и более поздней версии.
@RestController = @Controller + @ResponseBody
@RestController
превращает помеченный класс в Spring-бин. Этот бин для конвертации входящих/исходящих данных использует Jackson message converter. Как правило целевые данные представлены в json или xml.
ResponseEntity необходим, только если мы хотим кастомизировать ответ, добавив к нему статус ответа. Во всех остальных случаях будем использовать @ResponseBody.
@GetMapping(value=”/resource”)
@ResponseBody
public Resource sayHello() { return resource; }
@PostMapping(value=”/resource”)
public ResponseEntity createResource() {
….
return ResponseEntity.created(resource).build();
}
Стандартные HTTP коды статусов ответов, которые можно использовать.
200 — SUCCESS
201 — CREATED
404 — RESOURCE NOT FOUND
400 — BAD REQUEST
401 — UNAUTHORIZED
500 — SERVER ERROR
Для @ResponseBody единственные состояния статуса это SUCCESS(200), если всё ок и SERVER ERROR(500), если произошла какая-либо ошибка.
Допустим мы что-то создали и хотим отправить статус CREATED(201). В этом случае мы используем ResponseEntity.
Концептуально всё просто, фильтры сервлетов могут перехватывать только HTTPServlets. Listeners могут перехватывать специфические события. Как перехватить события которые относятся ни к тем не другим?
Фильтры и перехватчики делают по сути одно и тоже: они перехватывают какое-то событие, и делают что-то до или после.
Java EE использует термин Filter, Spring называет их Interceptors.
Именно здесь AOP используется в полную силу, благодаря чему возможно перехватывание вызовов любых объектов
Model — интерфейс, ModelMap его реализация..
ModelAndView является контейнером для пары, как ModelMap и View.
Обычно я люблю использовать ModelAndView. Однако есть так же способ когда мы задаем необходимые атрибуты в ModelMap, и возвращаем название View обычной строкой из метода контроллера.
Метод addAttribute отделяет нас от работы с базовой структурой hashmap. По сути addAttribute это обертка над put, где делается дополнительная проверка на null. Метод addAttribute в отличии от put возвращает modelmap.
model.addAttribute(“attribute1”,”value1”).addAttribute(“attribute2”,”value2”);
Нам это может понадобиться, если мы, например, захотим взять некоторое значение с HTML страницы и сохранить его в БД. Для этого нам надо это значение переместить в контроллер Спринга.
Если мы будем использовать Spring MVC form tags, Spring автоматически свяжет переменные на HTML странице с Бином Спринга.
Если мне придется с этим работать, я обязательно буду смотреть официальную документацию Spring MVC Form Tags.
Hibernate Validator никак не связан с БД. Это просто библиотека для валидации.
Hibernate Validator версии 5.x является эталонной реализацией Bean Validation 1.1
Так же если взглянуть по адресу http://beanvalidation.org/2.0, то Hibernate Validator является единственным, который сертифицирован.
Расположение статических ресурсов можно настроить. В документации Spring Boot рекомендуется использовать /static, или /public, или /resources, или /META-INF/resources
В случае GET запроса передаваемые параметры являются частью url, и все маршрутизаторы, через которые пройдет наш GET запрос, смогут их прочитать.
В случае POST запроса передаваемые параметры являются частью тела запроса. При использовании HTTPs, тело запроса шифруется. Следовательно, использование POST запросов является более безопасным
Пример:
http://localhost:8080/login?name=Ranga&name=Ravi&name=Sathish
Да, можно принять все значения, используя массив в методе контроллера
public String method(@RequestParam(value="name") String[] names){
}
Хочу поблагодарить пользователя хабра jd2050, за помощь с переводом.
Комментарии (20)
kkorsakoff
07.03.2018 17:51-128 неверный ответ, опасный даже. без шифрования промежуточные узлы могут прочитать и тело и адрес. С шифрованием не прочитать ни тело ни адрес запроса. А GET/POST история совсем другая. История браузера, глаза соседа, случайное копирование из адресной строки, кеширование, идемпотентность.
PqDn Автор
07.03.2018 17:53Но там же есть и уточнение про https
kkorsakoff
07.03.2018 18:02в том и дело, что нарушена причинно-следственная связь. HTTPS в действительности шифрует весь обмен, включая тело и заголовки и стартовую строку. Отсутствие HTTPS делает уязвимым для перехвата весь обмен, включая тело, заголовки и стартовую строку. То есть разницу между GET и POST объяснить конфиденциальностью (имею ввиду именно перехват, как в контексте статьи) нельзя даже за уши. А существенная разница как раз в другом.
kagary06
07.03.2018 17:52Выскажу, возможно непопулярную мысль, но список этих вопросов (и ответов тех людей, которые их сформировали на ресурсе www.springboottutorial.com) с большей вероятностью создадут больше путаницы и недопонимания между различными группами людей, прочитав данную статью (опытные специалисты, новички, HR, начинающие PM, и др.)
Первое что бросается в глаза — это сам ресурс. Он спроектирован по большей части как рекламная площадка для сайта с курсами с сайта in28minutes[com], где все статьи специально сделаны так, чтобы привлечь внимание.
[2 бесплатных руководства по прохождению интервью, 90% скидка для нашего курса]
На сайте я нашел в основном статьи с заголовками «10 шагов для изучения технологии/фреймворка X», а также списки с публичными репозиториями других людей на Github, где авторы, не сильно вдаваясь в код и технические подробности, при помощи пары фраз объясняют как это все запустить и что с чем связано.
Также я не вижу, чтобы на вопросы из списка был дан прямой и ясный ответ по сути этого вопроса.
Некоторые ответы на вопросы состоят из одного предложения из которого ответ не является хоть отдаленно полным. (особенно это касается 16 вопроса).
Не знаю откуда авторы данного текста составили этот список вопросов, но неужели в отдельно взятой стране этого действительно достаточно для того, чтобы стать начинающим веб-разработчиком с навыками Spring?
Считаю что данный материал явно не выполняет то, что обещает:
Этот небольшой список вопросов даст вам понимание самых важных концепций Spring, а так же поможет подготовиться к собеседованию
PqDn Автор
07.03.2018 17:56Считаю что данный материал явно не выполняет то, что обещает:
Согласен, ответы местами так себе.
Мне вот нравится список самих вопросов.
Для разминки на собеседовании самое тоigor_suhorukov
08.03.2018 16:29В том то и недостаток таких списков, что все их заучивают) И не понимают. Гораздо веселее решать практические задачки по Spring вместе с кандидатом на компьютере.
jeka_odessit
08.03.2018 00:50+1Это хорошо для начала. После этого я бы спросил например о cycle dependency что нибудь. ConditionalOn-Property/Class и т.п. с интересным примером. Как spring-managed bean получить без Autowire/Inject (ну и отличия этой пары, кстати). Потом можно попросить объяснить на примере как бы человек сделал что-то типа @EnableMyCoolFeature, по типу сприг-бут.
PloadyFree
08.03.2018 01:1519 Какая минимальная версия Java поддерживается в Spring Boot 2 и Spring 5?
Spring 5.0 и Spring Boot 2.0 поддерживают Java 8 и более поздней версии.
Да ладно? Почему-то на start.spring.io можно без проблем выбрать Spring Boot 2.0.0 и Java 7, при этом всё вполне себе будет работать.
Конечно, я не считаю, что есть хоть какой-то смысл создавать новый проект на второй версии Spring Boot и при этом использовать Java 7, но либо вопрос некорректен, либо Вы просто не удосужились найти правдивую информацию.igor_suhorukov
08.03.2018 16:32Потому что в Spring 5.0 и Spring Boot 2.0 под капотом много где lambda и API из java 8 используются. Попробуйте собрать проект с animal sniffer и указать jdk 7 ;-)
deilux
10.03.2018 01:42Ответы на почти все эти вопросы гуглятся за пару минут. Потому что являются частными случаями или ответами на вопрос "а на какие кнопки нужно нажать, чтобы во фреймворке Х сделать всем известную и понятную вещь У". Подобное действительно ещё спрашивают?
DSolodukhin
Странный ответ, учитывая, что если у нас HTTP, то и GET и POST отправляются открытым текстом, а при HTTPS у нас шифруется соединение полностью, в том числе и url.
Насколько я помню, можно в качестве аргумента использовать любую подходящую коллекцию: List, Set
vooft
Можно еще как минимум через запятую перечислить значения, и тогда он сам разобьет на отдельные значения и положит в коллекцию.
webkumo
Теоретически можно из истории гет-параметры вытащить можно (и при xss есть какие-то шансы), в то время как post-параметры вытащить скриптом не удастся.
venom280
Дело в том, что в отличии от POST запроса содержимое GET запроса осядет на каждом узле через который этот запрос прошел. Посмотрите что Apache записывает в access.log
Помимо логов запросы можно сохранять и в других местах для последующей аналитики/статистики. Например статистика просмотров определенного URL.
При особом умении можно добиться чтобы конфиденциальные данные от твоего сервиса можно было искать в google по inurl.
Так что для конфиденциальной информации только POST.
Видимо автор оригинального поста поленился разобраться и надергал по паре предложений из гугла.
venom280
И HTTPS в ответе тоже не отсюда. HTTPS защитит трафик от промежуточных узлов, но конечный сервер расшифрует все содержимое перед обработкой запроса и положит весь GET запрос в свой лог.
Szer
Ответ ещё страннее, учитывая что GET запросом можно точно так же body передавать.
Это считается антипаттерном и некоторые REST-клиенты (постман вроде) не разрешают body в GET, но тем не менее разница между GET и POST вкладывается человеком, а никак не протоколом.