{"id":326622,"date":"2021-07-18T21:00:16","date_gmt":"2021-07-18T21:00:16","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=326622"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=326622","title":{"rendered":"Spring Boot + BeanPostProcessor \u0438\u043b\u0438 \u043a\u0430\u043a \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u043e\u0442\u0432\u0435\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u0447\u0430\u0441\u0442\u044c 2"},"content":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<h2>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442, \u0434\u0440\u0443\u0437\u044c\u044f! \u042d\u0442\u043e \u0432\u0442\u043e\u0440\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u0440\u043e \u043e\u0431\u0435\u0440\u0442\u043a\u0443 \u043e\u0442\u0432\u0435\u0442\u043e\u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u043e \u0442\u043e, \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c BeanPostProcessor \u0438 \u0434\u043b\u044f \u0447\u0435\u0433\u043e \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0443\u0436\u043d\u043e &#8212; \u044d\u0442\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u043e\u0441\u044b\u043b \u0441\u0442\u0430\u0442\u044c\u0438. \u0421\u0434\u0435\u043b\u0430\u0435\u043c \u043c\u044b \u044d\u0442\u043e \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0432 \u043f\u0440\u043e\u0435\u043a\u0442 \u0438\u0437 <a href=\"https:\/\/habr.com\/ru\/post\/567056\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438<\/a>.&nbsp;<\/p>\n<p>\u041f\u043e\u0434 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0441 \u043d\u0438\u043a\u043e\u043c <a class=\"mention\" href=\"\/users\/maxzh83\">@maxzh83<\/a> \u0443\u043a\u0430\u0437\u0430\u043b \u043d\u0430 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u043d\u0435\u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 &#8212; \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u0441\u0435\u0440\u0432\u0438\u0441 IWrapperService, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0438\u0437-\u0437\u0430 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0438\u0434\u0435\u0442 \u0438\u043d\u0436\u0435\u043a\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430.<\/p>\n<pre><code class=\"java\">private final IWrapperService wrapperService;<\/code><\/pre>\n<p>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0442\u043e, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0448\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u043d\u0435\u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0441\u043f\u0440\u0438\u043d\u0433\u0430 &#8212; \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439. \u0418 \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0441\u043f\u0440\u0438\u043d\u0433\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e BeanPostProcessor \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438.<\/p>\n<h2>\u0412\u0441\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u043c, \u0447\u0442\u043e \u0433\u043e\u0442\u043e\u0432\u043e \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442<\/h2>\n<p>\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u0442\u044c, \u0447\u0442\u043e \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0432 <a href=\"https:\/\/habr.com\/ru\/post\/567056\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a>. \u041a\u043e\u0434 \u043d\u0430 <a href=\"https:\/\/github.com\/Emilikan\/ResponseWrapperLib\/tree\/master\" rel=\"noopener noreferrer nofollow\">GitHub \u043d\u0430 \u0432\u0435\u0442\u043a\u0435 master<\/a>.<\/p>\n<details class=\"spoiler\">\n<summary>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e \u0442\u043e, \u0447\u0442\u043e \u0443\u0436\u0435 \u0431\u044b\u043b\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u043e<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0441\u0442\u0430\u0440\u0442\u0435\u0440, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 2 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438: <em>@DisableResponseWrapper<\/em> \u0438 <em>@EnableResponseWrapper<\/em>, \u0430 \u0442\u0430\u043a\u0436\u0435 2 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430: <em>IWrapperModel<\/em> \u0438 <em>IWrapperService<\/em>, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043e\u0442\u0432\u0435\u0442\u044b \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u0432 \u043d\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441.<\/p>\n<p>\u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0430\u043a\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430, \u0432 \u0441\u0442\u0430\u0440\u0442\u0435\u0440\u0435 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u043a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <em>ResponseBodyAdvice&lt;Object&gt;<\/em> \u0438 \u0430\u043d\u043d\u043e\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>@ControllerAdvice(annotations = EnableResponseWrapper.class)<\/code><\/p>\n<pre><code class=\"java\">@AllArgsConstructor @ControllerAdvice(annotations = EnableResponseWrapper.class) public class ResponseWrapperAdvice implements ResponseBodyAdvice&lt;Object&gt; { \t... }<\/code><\/pre>\n<blockquote>\n<p>\u0410\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f <code>@ControllerAdvice(annotations = EnableResponseWrapper.class)<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u0447\u0442\u043e \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u0440\u0430\u0437\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u043c\u0438. \u0422\u0430\u043a\u0436\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u043d\u0430\u0448\u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u0431\u0443\u0434\u0443\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043c\u0435\u0447\u0435\u043d\u044b @EnableResponseWrapper.<\/p>\n<p>\u041a\u043b\u0430\u0441\u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <em>ResponseBodyAdvice&lt;&gt;<\/em>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043e\u0442\u0432\u0435\u0442, \u043f\u043e\u0441\u043b\u0435 \u0435\u0433\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u043c @ResponseBody \u0438\u043b\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u043c <em>ResponseEntity<\/em>, \u043d\u043e \u0434\u043e \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0442\u0435\u043b\u043e \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <em>HttpMessageConverter.<\/em><\/p>\n<\/blockquote>\n<p>\u0412 \u043a\u043b\u0430\u0441\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0431\u044b\u043b\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c 2 \u043c\u0435\u0442\u043e\u0434\u0430:<\/p>\n<pre><code class=\"java\">public boolean supports(MethodParameter returnType, @NonNull Class converterType)<\/code><\/pre>\n<p>&#8212; \u043c\u0435\u0442\u043e\u0434 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u0432\u0445\u043e\u0434\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u043c \u043a \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 false &#8212; \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0442\u043e\u0447\u043a\u0438 \u0432\u0445\u043e\u0434\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442.<\/p>\n<pre><code class=\"java\">public Object beforeBodyWrite(@Nullable Object body, @NonNull MethodParameter returnType, @NonNull MediaType selectedContentType, @NonNull Class selectedConverterType, @NonNull ServerHttpRequest request, @NonNull ServerHttpResponse response)<\/code><\/pre>\n<p>&#8212; \u043c\u0435\u0442\u043e\u0434 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0442\u043e\u0447\u043a\u0438 \u0432\u0445\u043e\u0434\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430. \u0412\u0435\u0440\u043d\u0443\u0442\u044c \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d api.<\/p>\n<p>\u042d\u0442\u043e\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043c\u044b \u043f\u043e\u043b\u043e\u0436\u0438\u043b\u0438 \u0432 \u0441\u0442\u0430\u0440\u0442\u0435\u0440 \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u0434\u0435\u043c\u043e-\u043f\u0440\u043e\u0435\u043a\u0442 \u043f\u043e\u0434 \u0434\u0430\u043d\u043d\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b.<\/p>\n<blockquote>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438 \u0434\u043b\u044f \u0438\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0441 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u043e\u0442\u0432\u0435\u0442\u043e\u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432. \u041f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u0445. (\u0425\u043e\u0440\u043e\u0448\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043e\u0431 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 <a href=\"https:\/\/habr.com\/ru\/post\/528116\/\" rel=\"noopener noreferrer nofollow\">https:\/\/habr.com\/ru\/post\/528116\/<\/a>)<\/p>\n<p>\u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f ControllerAdvice+ResponseBodyAdvice \u0438 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0439 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0431\u043e\u043b\u0435\u0435 \u0433\u0438\u0431\u043a\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043b\u044e\u0431\u044b\u0445 \u043e\u0442\u0432\u0435\u0442\u043e\u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043c\u0435\u0442\u043e\u0434\u0435, \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0435, \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u0438 \u043e\u0442\u0432\u0435\u0442\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430.<\/p>\n<\/blockquote>\n<\/div>\n<\/details>\n<h2>\u0412\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438<\/h2>\n<p>\u041c\u044b \u0445\u043e\u0442\u0438\u043c \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430-\u043e\u0431\u0435\u0440\u0442\u043a\u0438 \u0441\u0432\u043e\u0439 \u0441\u0435\u0440\u0432\u0438\u0441.&nbsp;<\/p>\n<p>\u0421\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438 \u0431\u044b\u0441\u0442\u0440\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 &#8212; \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u0435\u043c, \u0447\u0442\u043e \u0443\u0436\u0435 \u0443\u043c\u0435\u0435\u0442 spring &#8212; \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439.&nbsp;<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432:<\/p>\n<pre><code class=\"java\">@Service @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface WrapperService {     Class&lt;? extends IWrapperModel&lt;?, ?&gt;&gt; wrapperModel(); }<\/code><\/pre>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u043d\u0430\u0448\u0430 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u0432\u0438\u0441\u0438\u0442 \u043d\u0430\u0434 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c &#8212; \u0442\u043e \u0432\u0435\u0448\u0430\u0435\u043c \u043d\u0430\u0434 \u043d\u0430\u0448\u0435\u0439 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0435\u0439 <em>@Service<\/em> &#8212; \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <em>@WrapperService<\/em> \u0432\u043c\u0435\u0441\u0442\u043e <em>@Service.<\/em><\/p>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c-\u043e\u0431\u0435\u0440\u0442\u043a\u0443 \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u043e \u043d\u0435\u0439 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430.<\/p>\n<h2>\u041d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0438<\/h2>\n<p>\u0421\u0440\u0430\u0437\u0443 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u0442\u0430\u0440\u0442\u0435\u0440 \u0431\u044b\u043b \u0431\u043e\u043b\u0435\u0435 \u0433\u0438\u0431\u043a\u0438\u043c.<\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c generic-\u0438. \u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043c\u043e\u0434\u0435\u043b\u0438:<\/p>\n<pre><code class=\"java\">public interface IWrapperModel&lt;Body, Data&gt; {         void setData(@Nullable Data data, @NonNull MethodInformation methodInformation);      default &lt;DataHelper&gt; void setDataHelper(@Nullable DataHelper data, @NonNull MethodInformation methodInformation){         @SuppressWarnings(\"unchecked\")         Data data1 = (Data) data;          setData(data1, methodInformation);     }      void setBody(@NonNull Body body, @NonNull MethodInformation methodInformation);      default &lt;BodyHelper&gt; void setBodyHelper(@NonNull BodyHelper body, @NonNull MethodInformation methodInformation) {         @SuppressWarnings(\"unchecked\")         Body body1 = (Body) body;          setBody(body1, methodInformation);     } }<\/code><\/pre>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u0445\u0435\u043b\u043f\u0435\u0440\u044b setBodyHelper \u0438 setDataHelper \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 Wildcard. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e helper-\u043c\u0435\u0442\u043e\u0434\u044b \u0438 \u0437\u0430\u0447\u0435\u043c \u043e\u043d\u0438 \u043d\u0443\u0436\u043d\u044b \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0435\u0441\u0442\u044c \u0432 <a href=\"https:\/\/docs.oracle.com\/javase\/tutorial\/java\/generics\/capture.html\" rel=\"noopener noreferrer nofollow\">\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a>.<\/p>\n<p>\u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0434\u0435\u043b\u0430\u0435\u043c \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430:<\/p>\n<pre><code class=\"java\">public interface IWrapperService&lt;Body, Data&gt; {     @Nullable     Data getData(@NonNull Body body);      default &lt;BodyHelper&gt; Data getDataHelper (@NonNull BodyHelper body) {         @SuppressWarnings(\"unchecked\")         Body body1 = (Body) body;          return getData(body1);     } }<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u043e\u0431\u0435\u0440\u0442\u043a\u0443 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0435, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0441 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<pre><code class=\"java\">@Getter @AllArgsConstructor public class MethodInformation {     @NonNull     private final MethodParameter returnType;     @NonNull     private final MediaType selectedContentType;     @NonNull     private final Class&lt;?&gt; selectedConverterType;     @NonNull     private final ServerHttpRequest request;     @NonNull     private final ServerHttpResponse response; } <\/code><\/pre>\n<h2>\u0418\u0437\u043c\u0435\u043d\u044f\u0435\u043c ResponseWrapperAdvice<\/h2>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0435, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c &#8212; \u044d\u0442\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0438\u043d\u0436\u0435\u043a\u0442 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 <em>ResponseWrapperAdvice.<\/em><\/p>\n<p>\u0412\u043c\u0435\u0441\u0442\u043e:<\/p>\n<pre><code class=\"java\">private final IWrapperService wrapperService;<\/code><\/pre>\n<p>\u041f\u0438\u0448\u0435\u043c:<\/p>\n<pre><code class=\"java\">private final List&lt;IWrapperService&lt;?, ?&gt;&gt; wrapperServiceList;<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c spring \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430\u0439\u0434\u0435\u0442 \u0438 \u0441\u043e\u0431\u0435\u0440\u0435\u0442 \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0435 \u043a\u043b\u0430\u0441\u0441\u044b, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0435 <em>IWrapperService<\/em> \u0441 \u043b\u044e\u0431\u044b\u043c\u0438 <em>Body<\/em> \u0438 <em>Data.<\/em><\/p>\n<p>\u041d\u0430\u043f\u0438\u0448\u0435\u043c \u043c\u0435\u0442\u043e\u0434 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 \u0442\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u043d\u0430\u0448\u0435\u043c\u0443 \u043a\u043b\u0430\u0441\u0441\u0443-\u043e\u0431\u0435\u0440\u0442\u043a\u0435.<\/p>\n<pre><code class=\"java\">... @NonNull private IWrapperService&lt;?, ?&gt; getWrapperService( \t\t@NonNull Class&lt;? extends IWrapperModel&lt;?, ?&gt;&gt; wrapperClass ) { \t\tIWrapperService&lt;?, ?&gt; wrapperService = null;  \t\tfor (IWrapperService&lt;?, ?&gt; iWrapperService : wrapperServiceList) { \t\t\t\tfor (Annotation annotation : iWrapperService.getClass().getAnnotations()) { \t\t\t\t\t\tif (annotation.annotationType() == WrapperService.class &amp;&amp; \t\t\t\t\t\t\t\t((WrapperService) annotation).wrapperModel()==wrapperClass \t\t\t\t\t\t){ \t\t\t\t\t\t\t\twrapperService = iWrapperService; \t\t\t\t\t\t\t\tbreak; \t\t\t\t\t\t} \t\t\t\t} \t\t}  \t\tif (wrapperService==null) { \t\t\t\tthrow new RuntimeException(\"\u041e\u0431\u0435\u0440\u0442\u043a\u0430 \u0431\u0435\u0437 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\"); \t\t} \t\treturn wrapperService; } ...<\/code><\/pre>\n<p>\u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>iWrapperService.getClass().getAnnotations()<\/code> \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0438 \u0438\u0449\u0435\u043c \u0441\u0440\u0435\u0434\u0438 \u043d\u0438\u0445 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e <em>@WrapperService<\/em>. \u0418\u0437 \u043d\u0435\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u043b\u0430\u0441\u0441-\u043e\u0431\u0435\u0440\u0442\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c \u0441 \u0442\u043e\u0439, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0441\u0435\u0439\u0447\u0430\u0441 \u0441\u0430\u043c\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@AllArgsConstructor @ControllerAdvice(annotations = EnableResponseWrapper.class) public class ResponseWrapperAdvice implements ResponseBodyAdvice&lt;Object&gt; {      private final List&lt;IWrapperService&lt;?, ?&gt;&gt; wrapperServiceList;      \/**      * \u041c\u0435\u0442\u043e\u0434 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d, \u0435\u0441\u043b\u0438 \u043f\u043e\u043c\u0435\u0447\u0435\u043d \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0435\u0439 {@link DisableResponseWrapper} &lt;br\/&gt; &lt;br\/&gt;      *      * @param returnType    the return type      * @param converterType the selected converter type      * @return {@code true} if {@link #beforeBodyWrite} should be invoked;      * {@code false} otherwise      *\/     @Override     public boolean supports(MethodParameter returnType, @NonNull Class converterType) {         for (Annotation a : returnType.getMethodAnnotations()) {             if (a.annotationType() == DisableResponseWrapper.class) {                 return false;             }         }          return true;     }      \/**      * \u041e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u043e\u0442\u0432\u0435\u0442      *      * @param body                  the body to be written      * @param returnType            the return type of the controller method      * @param selectedContentType   the content type selected through content negotiation      * @param selectedConverterType the converter type selected to write to the response      * @param request               the current request      * @param response              the current response      * @return the body that was passed in or a modified (possibly new) instance      *\/     @SneakyThrows     @Override     @Nullable     public Object beforeBodyWrite(             @Nullable Object body,             @NonNull MethodParameter returnType,             @NonNull MediaType selectedContentType,             @NonNull Class selectedConverterType,             @NonNull ServerHttpRequest request,             @NonNull ServerHttpResponse response     ) {         MethodInformation methodInformation = new MethodInformation(returnType, selectedContentType, selectedConverterType, request, response);          if (body == null) {             return null;         }          \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c wrapperClass \u0438\u0437 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438         Class&lt;? extends IWrapperModel&lt;?, ?&gt;&gt; wrapperClass = null;         for (Annotation annotation : returnType.getContainingClass().getAnnotations()) {             if (annotation.annotationType() == EnableResponseWrapper.class) {                 wrapperClass = ((EnableResponseWrapper) annotation).wrapperClass();                 break;             }         }          if (wrapperClass == null) {             return body;         }          \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0431\u044b\u043b \u043b\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u043d Collection \u0438\u043b\u0438 \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a Collection         if (Collection.class.isAssignableFrom(body.getClass())) {             try {                 Collection&lt;?&gt; bodyCollection = (Collection&lt;?&gt;) body;                 \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e collection \u043d\u0435 \u043f\u0443\u0441\u0442\u043e\u0439                 if (bodyCollection.isEmpty()) {                     return body;                 }                 \/\/ \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438                 return generateListOfResponseWrapper(bodyCollection, wrapperClass, methodInformation);             } catch (Exception e) {                 return body;             }         }         \/\/ \u0435\u0441\u043b\u0438 \u043d\u0435 collection         return generateResponseWrapper(body, wrapperClass, methodInformation);     }      \/**      * \u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0431\u0435\u0440\u0442\u043e\u043a \u0434\u043b\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 (\u0442\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u044c \u0441\u043f\u0438\u0441\u043a\u0430)      *      * @param bodyCollection \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c      * @param wrapperClass   \u043e\u0431\u044a\u0435\u043a\u0442 \u043e\u0431\u0435\u0440\u0442\u043a\u0438      * @return \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0431\u0435\u0440\u0442\u043e\u043a      *\/     @NonNull     private List&lt;Object&gt; generateListOfResponseWrapper(             @NonNull Collection&lt;?&gt; bodyCollection,             @NonNull Class&lt;? extends IWrapperModel&lt;?, ?&gt;&gt; wrapperClass,             @NonNull MethodInformation methodInformation     ) {         return bodyCollection.stream()                 .map((t) -&gt; t == null ?                         null :                         generateResponseWrapper(t, wrapperClass, methodInformation)                 )                 .collect(Collectors.toList());     }      \/**      * \u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u043e\u0431\u0435\u0440\u0442\u043a\u0443 \u0432\u043e\u043a\u0440\u0443\u0433 \u043e\u0431\u044a\u0435\u043a\u0442\u0430      *      * @param body         \u043e\u0431\u044a\u0435\u043a\u0442 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432 \u043e\u0431\u0435\u0440\u0442\u043a\u0443      * @param wrapperClass \u043e\u0431\u044a\u0435\u043a\u0442 \u043e\u0431\u0435\u0440\u0442\u043a\u0438      * @return \u043e\u0431\u0435\u0440\u0442\u043a\u0430      *\/     @NonNull     @SneakyThrows     private IWrapperModel&lt;?, ?&gt; generateResponseWrapper(             @NonNull Object body,             @NonNull Class&lt;? extends IWrapperModel&lt;?, ?&gt;&gt; wrapperClass,             @NonNull MethodInformation methodInformation     ) {         \/\/ wrapperClass \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u0435\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0431\u0435\u0437 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 - \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 IWrapperModel         IWrapperModel&lt;?, ?&gt; wrapper = wrapperClass.getDeclaredConstructor().newInstance();         wrapper.setBodyHelper(body, methodInformation);         wrapper.setDataHelper(getWrapperService(wrapperClass).getDataHelper(body), methodInformation);         return wrapper;     }      \/**      * \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043d\u0443\u0436\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u0435\u0440\u0442\u043a\u0438      *      * @param wrapperClass \u043e\u0431\u0435\u0440\u0442\u043a\u0430, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0430\u0439\u0442\u0438 \u0441\u0435\u0440\u0432\u0438\u0441      * @return \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u043e\u0431\u0435\u0440\u0442\u043a\u0438      * @throws RuntimeException \u0432 \u043a\u043e\u0434\u0435 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u0431\u0435\u0437 \u0441\u0435\u0440\u0432\u0438\u0441\u0430      *\/     @NonNull     private IWrapperService&lt;?, ?&gt; getWrapperService(             @NonNull Class&lt;? extends IWrapperModel&lt;?, ?&gt;&gt; wrapperClass     ) {         IWrapperService&lt;?, ?&gt; wrapperService = null;          for (IWrapperService&lt;?, ?&gt; iWrapperService : wrapperServiceList) {             for (Annotation annotation : iWrapperService.getClass().getAnnotations()) {                 if (annotation.annotationType() == WrapperService.class &amp;&amp;                         ((WrapperService) annotation).wrapperModel()==wrapperClass                 ){                     wrapperService = iWrapperService;                     break;                 }             }         }          if (wrapperService==null) {             throw new RuntimeException(\"\u041e\u0431\u0435\u0440\u0442\u043a\u0430 \u0431\u0435\u0437 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\");         }         return wrapperService;     }  }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0432\u043f\u043e\u043b\u043d\u0435 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439, \u043d\u043e \u043d\u0435 \u043b\u0443\u0447\u0448\u0438\u0439. \u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043c\u0435\u0442\u043e\u0434 <em>getWrapperService<\/em> \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043f\u0440\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0435, \u0432 \u0447\u0435\u043c \u043d\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438. \u042d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440.<\/p>\n<p>\u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u043a\u0430\u043a \u043c\u043d\u0435 \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u043a\u0443\u0434\u0430 \u043b\u043e\u0433\u0438\u0447\u043d\u0435\u0435 \u0438\u043d\u0436\u0435\u043a\u0442\u0438\u0442\u044c \u043d\u0435 \u0441\u043f\u0438\u0441\u043e\u043a \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0438 \u0437\u0430\u0442\u0435\u043c \u043f\u043e \u043d\u0435\u043c\u0443 \u0438\u0441\u043a\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0439 \u043f\u0435\u0440\u0435\u0431\u043e\u0440\u043e\u043c, \u0430 \u0441\u0440\u0430\u0437\u0443 \u043c\u0430\u043f\u0443, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u043a\u043b\u0430\u0441\u0441-\u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u043f\u0440\u043e\u0442\u0438\u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u0430.<\/p>\n<p>\u0421\u043f\u0440\u0438\u043d\u0433 \u0443\u043c\u0435\u0435\u0442 \u0438\u043d\u0436\u0435\u043a\u0442\u0438\u0442\u044c \u043c\u0430\u043f\u044b, \u043d\u043e \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442 (\u0438 \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d) \u0441\u0430\u043c \u0434\u043e\u0433\u0430\u0434\u0430\u0442\u044c\u0441\u044f \u0431\u0440\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441-\u043e\u0431\u0435\u0440\u0442\u043a\u0443 \u0438\u0437 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438. \u0414\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432 \u0441\u043f\u0440\u0438\u043d\u0433 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0431\u0438\u043d\u043e\u0432 (\u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438\u0445 \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442). \u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u0434\u043e\u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0431\u0438\u043d\u043e\u0432 &#8212; \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 <em>BeanPostProcessor.<\/em><\/p>\n<p><strong>\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439: <\/strong><a href=\"https:\/\/github.com\/Emilikan\/ResponseWrapperLib\/tree\/many-services-inject-through-list\" rel=\"noopener noreferrer nofollow\"><strong>GitHub<\/strong><\/a><\/p>\n<h2>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u0442\u0435\u043e\u0440\u0438\u0438<\/h2>\n<p>\u0412 \u0441\u043f\u0440\u0438\u043d\u0433\u0435 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u044d\u0442\u0430\u043f\u044b \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430, \u0432 \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445, \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438, \u043c\u043e\u0436\u043d\u043e \u0432\u043a\u043b\u0438\u043d\u0438\u0442\u044c\u0441\u044f \u0441\u0430\u043c\u043e\u043c\u0443:<\/p>\n<ol>\n<li>\n<p>\u041f\u0430\u0440\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 (<em>XML<\/em>, <em>JavaConfig<\/em> \u0438 \u0442\u0434). \u041f\u043e\u0441\u043b\u0435 \u043f\u0430\u0440\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f <em>BeanDefenition<\/em> &#8212; \u043c\u0435\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0430\u044f \u0431\u0443\u0434\u0443\u0449\u0438\u0439 \u0431\u0438\u043d;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0443\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0445 <em>BeanDefinition<\/em> &#8212; \u043d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u0432\u043b\u0438\u044f\u0442\u044c \u043d\u0430 \u0442\u043e, \u043a\u0430\u043a\u0438\u043c\u0438 \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0448\u0438 \u0431\u0438\u043d\u044b \u0435\u0449\u0435 \u0434\u043e \u0438\u0445 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f;<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 <em>FactoryBean<\/em> &#8212; \u043c\u043e\u0436\u043d\u043e \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0444\u0430\u0431\u0440\u0438\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0431\u0438\u043d\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430;<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u0432 \u0431\u0438\u043d\u043e\u0432 &#8212; \u0442\u0443\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0438\u043b\u0438 \u043f\u0440\u043e\u043a\u0441\u0435\u0439. \u041d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043c\u043e\u0436\u043d\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043d\u0436\u0435\u043a\u0442 \u043f\u043e\u043b\u044f \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0445 \u0431\u0438\u043d\u043e\u0432 &#8212; <em>BeanPostProcessor<\/em> &#8212; \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u043e, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e. \u041d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0431\u0438\u043d\u0430 \u0443\u0436\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b\u0441\u044f \u0438 \u0431\u0438\u043d \u0441\u043e\u0437\u0434\u0430\u043d, \u043d\u043e \u0431\u0438\u043d \u0435\u0449\u0435 \u043d\u0435 \u043f\u043e\u043f\u0430\u043b \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442.<\/p>\n<\/li>\n<\/ol>\n<p>\u0425\u043e\u0440\u043e\u0448\u0430\u044f \u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0430\u044f <a href=\"https:\/\/habr.com\/ru\/post\/222579\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u044f<\/a> \u043f\u0440\u043e \u044d\u0442\u0430\u043f\u044b \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430.<\/p>\n<p>\u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 <em>BeanPostProcessor<\/em> &#8212; \u044d\u0442\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 &#8212; \u0435\u0433\u043e \u0431\u0438\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0434\u0435\u043a\u043b\u0430\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u043e\u0434\u043d\u0438\u043c \u0438\u0437 4 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432. \u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 2 \u043c\u0435\u0442\u043e\u0434\u0430 <em>postProcessBeforeInitialization<\/em> \u0438 <em>postProcessAfterInitialization<\/em>. \u041f\u0435\u0440\u0432\u044b\u0439 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u043e PostConstruct, \u0432\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u0441\u043b\u0435. \u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0431\u0438\u043d.<\/p>\n<h2>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0437\u0430\u0434\u0430\u0447\u0438 \u0447\u0435\u0440\u0435\u0437 BeanPostProcessor<\/h2>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430, \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043d\u043e\u0432\u0430\u044f \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u0442\u044c \u043c\u0435\u0441\u0442\u043e \u0434\u043b\u044f \u0438\u043d\u0436\u0435\u043a\u0442\u0430 \u043d\u0430\u0448\u0435\u0439 \u043c\u0430\u043f\u044b:<\/p>\n<pre><code class=\"java\">@Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface InjectWrapperServiceMap { }<\/code><\/pre>\n<p>\u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0441\u0430\u043c \u043a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 <em>BeanPostProcessor:<\/em><\/p>\n<pre><code class=\"java\">@Component @AllArgsConstructor public class InjectWrapperServiceMapBeanPostProcessor implements BeanPostProcessor {   private final ApplicationContext applicationContext; \t... }<\/code><\/pre>\n<p>\u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0431\u0438\u043d\u043e\u0432 \u0432 \u043c\u0430\u043f\u0443 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0437\u0430\u0438\u043d\u0436\u0435\u043a\u0442\u0438\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442. \u0422\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0439 \u0431\u0438\u043d &#8212; \u0442\u043e \u0438\u043d\u0436\u0435\u043a\u0442\u0438\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0438\u043c\u0435\u0435\u043c \u043f\u0440\u0430\u0432\u043e.<\/p>\n<p>\u0418\u0437 \u0434\u0432\u0443\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d. \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043d\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0435\u0439 \u0431\u0443\u0434\u0435\u043c \u0434\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f <em>PostConstruct<\/em>, \u0442\u043a \u043c\u0435\u0442\u043e\u0434, \u0430\u043d\u043d\u043e\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 <em>PostConstruct<\/em> \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0449\u0438\u043c, \u0440\u0430\u0431\u043e\u0442\u044e\u0449\u0438\u043c \u0442\u043e\u0433\u0434\u0430, \u043a\u043e\u0433\u0434\u0430 \u0432\u0441\u0435 \u0431\u0438\u043d\u044b \u0431\u044b\u043b\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u044b \u043a \u043a\u043b\u0430\u0441\u0441\u0443.<\/p>\n<pre><code class=\"java\">... @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { \t\tsetFieldInjects(bean); \t\tsetMethodInject(bean); \t\treturn bean; } ...<\/code><\/pre>\n<p>\u041c\u0435\u0442\u043e\u0434 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043c\u0430\u043f\u044b \u043a\u043b\u0430\u0441\u0441\u0430 \u043e\u0431\u0435\u0440\u0442\u043a\u0438 \u043f\u0440\u043e\u0442\u0438\u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u0430:<\/p>\n<pre><code class=\"java\">... private Map&lt;Class&lt;? extends IWrapperModel&lt;?, ?&gt;&gt;, IWrapperService&gt; getWrapperServiceMap() { \t\tMap&lt;String, IWrapperService&gt; beansOfType = applicationContext.getBeansOfType(IWrapperService.class);  \t\treturn beansOfType.values().stream() \t\t\t\t\t\t.collect(Collectors.toMap( \t\t\t\t\t\t\t\t\t\t(t) -&gt; { \t\t\t\t\t\t\t\t\t\t\t\tif (!t.getClass().isAnnotationPresent(WrapperService.class)) { \t\t\t\t\t\t\t\t\t\t\t\t\t\tthrow new RuntimeException(\"\u041d\u0435 \u0432\u0441\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0435 IWrapperService, \u0430\u043d\u043d\u043e\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b @WrapperService\"); \t\t\t\t\t\t\t\t\t\t\t\t}                             return t.getClass().getAnnotation(WrapperService.class).wrapperModel(); \t\t\t\t\t\t\t\t\t\t}, \t\t\t\t\t\t\t\t\t\t(t) -&gt; t \t\t\t\t\t\t\t\t\t\t) \t\t\t\t\t\t); } ...<\/code><\/pre>\n<p><code>applicationContext.getBeansOfType(IWrapperService.class)<\/code> &#8212; \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u0431\u0438\u043d\u044b \u0438\u0437 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442 <em>IWrapperService.<\/em><\/p>\n<p><code>t.getClass().getAnnotation(WrapperService.class).wrapperModel()<\/code> &#8212; \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u043b\u0430\u0441\u0441-\u043e\u0431\u0435\u0440\u0442\u043a\u0443 \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u0430.<\/p>\n<p>\u041c\u0435\u0442\u043e\u0434\u044b \u0438\u043d\u0436\u0435\u043a\u0442\u0430 \u0432 \u043c\u0435\u0442\u043e\u0434 \u0438 \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e:<\/p>\n<pre><code class=\"java\">... @SneakyThrows private void setMethodInject(Object bean) {   \tSet&lt;Method&gt; methods = Arrays.stream(bean.getClass().getDeclaredMethods()) \t\t\t\t\t\t.filter(method -&gt; method.isAnnotationPresent(InjectWrapperServiceMap.class)) \t\t\t\t\t\t.collect(Collectors.toSet());  \t\tfor (Method method : methods) { \t\t\t\tmethod.invoke(bean, getWrapperServiceMap()); \t\t} }  @SneakyThrows private void setFieldInjects(Object bean) {   \tSet&lt;Field&gt; fields = Arrays.stream(bean.getClass().getDeclaredFields()) \t\t\t\t\t\t.filter(field -&gt; field.isAnnotationPresent(InjectWrapperServiceMap.class)) \t\t\t\t\t\t.collect(Collectors.toSet());  \t\tfor (Field field : fields) { \t\t\t\tfield.setAccessible(true); \t\t\t\tfield.set(bean, getWrapperServiceMap()); \t\t} } ...<\/code><\/pre>\n<p>\u0412\u043d\u0430\u0447\u0430\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u043c\u0435\u0442\u043e\u0434\u044b\/\u043f\u043e\u043b\u044f \u043a\u043b\u0430\u0441\u0441\u0430 \u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u0443\u0435\u043c \u0438\u0445 \u043f\u043e \u043d\u0430\u043b\u0438\u0447\u0438\u044e \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 <em>@InjectWrapperServiceMap.<\/em><\/p>\n<p>\u0414\u043b\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u0430, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u044f \u0432 \u043d\u0435\u0433\u043e \u043c\u0430\u043f\u0443 <code>method.invoke(bean, getWrapperServiceMap());<\/code><\/p>\n<p>\u0414\u043b\u044f \u043f\u043e\u043b\u044f \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0433\u043b\u0438 \u0432 \u043f\u043e\u043b\u0435 \u0447\u0442\u043e-\u043b\u0438\u0431\u043e \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c \u0437\u0430\u043f\u0438\u0441\u044c <code>field.set(bean, getWrapperServiceMap());<\/code><\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 InjectWrapperServiceMapBeanPostProcessor<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@Component @AllArgsConstructor public class InjectWrapperServiceMapBeanPostProcessor implements BeanPostProcessor {      private final ApplicationContext applicationContext;      @Override     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {         setFieldInjects(bean);         setMethodInject(bean);         return bean;     }      @SneakyThrows     private void setMethodInject(Object bean) {         Set&lt;Method&gt; methods = Arrays.stream(bean.getClass().getDeclaredMethods())                 .filter(method -&gt; method.isAnnotationPresent(InjectWrapperServiceMap.class))                 .collect(Collectors.toSet());          for (Method method : methods) {             method.invoke(bean, getWrapperServiceMap());         }     }      @SneakyThrows     private void setFieldInjects(Object bean) {         Set&lt;Field&gt; fields = Arrays.stream(bean.getClass().getDeclaredFields())                 .filter(field -&gt; field.isAnnotationPresent(InjectWrapperServiceMap.class))                 .collect(Collectors.toSet());          for (Field field : fields) {             field.setAccessible(true);             field.set(bean, getWrapperServiceMap());         }     }      private Map&lt;Class&lt;? extends IWrapperModel&lt;?, ?&gt;&gt;, IWrapperService&gt; getWrapperServiceMap() {         Map&lt;String, IWrapperService&gt; beansOfType = applicationContext.getBeansOfType(IWrapperService.class);          return beansOfType.values().stream()                 .collect(Collectors.toMap(                         (t) -&gt; {                             if (!t.getClass().isAnnotationPresent(WrapperService.class)) {                                 throw new RuntimeException(\"\u041d\u0435 \u0432\u0441\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0435 IWrapperService, \u0430\u043d\u043d\u043e\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b @WrapperService\");                             }                             return t.getClass().getAnnotation(WrapperService.class).wrapperModel();                         },                         (t) -&gt; t                         )                 );     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0412 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0431\u0438\u043d\u043e\u0432 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u0431\u0438\u043d:<\/p>\n<pre><code class=\"java\">... @Bean @ConditionalOnMissingBean public InjectWrapperServiceMapBeanPostProcessor responseWrapperBeanPostProcessor() { \t\treturn new InjectWrapperServiceMapBeanPostProcessor(applicationContext); } ...<\/code><\/pre>\n<p>\u041a \u0431\u0438\u043d\u0443 <em>ResponseWrapperAdvice<\/em> \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c <code>@DependsOn(value = \"responseWrapperBeanPostProcessor\")<\/code> \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0431\u0438\u043d \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043b\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0431\u0438\u043d\u0430 <em>BPP.<\/em><\/p>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b <em>@DependsOn<\/em> \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0430\u0434 \u043a\u043b\u0430\u0441\u0441\u043e\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e <code>@ComponentScan(\"ru.emilnasyrov.lib.response.wrapper\")<\/code><\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 ResponseWrapperAutoConfiguration<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@Configuration @AutoConfigureAfter(WebMvcAutoConfiguration.class) @RequiredArgsConstructor @ComponentScan(\"ru.emilnasyrov.lib.response.wrapper\") public class ResponseWrapperAutoConfiguration {      private final ApplicationContext applicationContext;      @Bean     @ConditionalOnMissingBean     @DependsOn(value = \"responseWrapperBeanPostProcessor\")     public ResponseWrapperAdvice responseWrapperAdvice() {         return new ResponseWrapperAdvice();     }      @Bean     @ConditionalOnMissingBean     public InjectWrapperServiceMapBeanPostProcessor responseWrapperBeanPostProcessor() {         return new InjectWrapperServiceMapBeanPostProcessor(applicationContext);     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e <em>@InjectWrapperServiceMap <\/em>\u0434\u043b\u044f \u0438\u043d\u0436\u0435\u043a\u0442\u0430 \u043c\u0430\u043f\u044b \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u0432 \u0432\u043d\u0443\u0442\u0440\u0438 \u043d\u0430\u0448\u0435\u0433\u043e \u0441\u0442\u0430\u0440\u0442\u0435\u0440\u0430, \u0442\u0430\u043a \u0438 \u0441\u043d\u0430\u0440\u0443\u0436\u0438.<\/p>\n<p>\u0412 <em>ResponseWrapperAdvice<\/em> \u0437\u0430\u0438\u043d\u0436\u0435\u043a\u0442\u0438\u043c \u043c\u0430\u043f\u0443:<\/p>\n<pre><code class=\"java\">... private Map&lt;Class&lt;? extends IWrapperModel&lt;?, ?&gt;&gt;, IWrapperService&lt;?, ?&gt;&gt; wrapperServiceMap;  @InjectWrapperServiceMap public void setWrapperServiceMap(Map&lt;Class&lt;? extends IWrapperModel&lt;?, ?&gt;&gt;, IWrapperService&lt;?, ?&gt;&gt; wrapperServiceMap) { \t\tthis.wrapperServiceMap = wrapperServiceMap; } ...<\/code><\/pre>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0435\u0435 \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 generateResponseWrapper \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"java\">private IWrapperModel&lt;?, ?&gt; generateResponseWrapper(...){ \t\t... \t\twrapper.setDataHelper(wrapperServiceMap.get(wrapperClass).getDataHelper(body), methodInformation); \t\t... }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 ResponseWrapperAdvice<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@NoArgsConstructor @ControllerAdvice(annotations = EnableResponseWrapper.class) public class ResponseWrapperAdvice implements ResponseBodyAdvice&lt;Object&gt; {      private Map&lt;Class&lt;? extends IWrapperModel&lt;?, ?&gt;&gt;, IWrapperService&lt;?, ?&gt;&gt; wrapperServiceMap;      @InjectWrapperServiceMap     public void setWrapperServiceMap(Map&lt;Class&lt;? extends IWrapperModel&lt;?, ?&gt;&gt;, IWrapperService&lt;?, ?&gt;&gt; wrapperServiceMap) {         this.wrapperServiceMap = wrapperServiceMap;     }      \/**      * \u041c\u0435\u0442\u043e\u0434 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d, \u0435\u0441\u043b\u0438 \u043f\u043e\u043c\u0435\u0447\u0435\u043d \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0435\u0439 {@link DisableResponseWrapper} &lt;br\/&gt; &lt;br\/&gt;      *      * @param returnType    the return type      * @param converterType the selected converter type      * @return {@code true} if {@link #beforeBodyWrite} should be invoked;      * {@code false} otherwise      *\/     @Override     public boolean supports(MethodParameter returnType, @NonNull Class converterType) {         for (Annotation a : returnType.getMethodAnnotations()) {             if (a.annotationType() == DisableResponseWrapper.class) {                 return false;             }         }          return true;     }      \/**      * \u041e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u043e\u0442\u0432\u0435\u0442      *      * @param body                  the body to be written      * @param returnType            the return type of the controller method      * @param selectedContentType   the content type selected through content negotiation      * @param selectedConverterType the converter type selected to write to the response      * @param request               the current request      * @param response              the current response      * @return the body that was passed in or a modified (possibly new) instance      *\/     @SneakyThrows     @Override     @Nullable     public Object beforeBodyWrite(             @Nullable Object body,             @NonNull MethodParameter returnType,             @NonNull MediaType selectedContentType,             @NonNull Class selectedConverterType,             @NonNull ServerHttpRequest request,             @NonNull ServerHttpResponse response     ) {         MethodInformation methodInformation = new MethodInformation(returnType, selectedContentType, selectedConverterType, request, response);          if (body == null) {             return null;         }          \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c wrapperClass \u0438\u0437 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438         Class&lt;? extends IWrapperModel&lt;?, ?&gt;&gt; wrapperClass = null;         for (Annotation annotation : returnType.getContainingClass().getAnnotations()) {             if (annotation.annotationType() == EnableResponseWrapper.class) {                 wrapperClass = ((EnableResponseWrapper) annotation).wrapperClass();                 break;             }         }          if (wrapperClass == null) {             return body;         }          \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0431\u044b\u043b \u043b\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u043d Collection \u0438\u043b\u0438 \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a Collection         if (Collection.class.isAssignableFrom(body.getClass())) {             try {                 Collection&lt;?&gt; bodyCollection = (Collection&lt;?&gt;) body;                 \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e collection \u043d\u0435 \u043f\u0443\u0441\u0442\u043e\u0439                 if (bodyCollection.isEmpty()) {                     return body;                 }                 \/\/ \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438                 return generateListOfResponseWrapper(bodyCollection, wrapperClass, methodInformation);             } catch (Exception e) {                 return body;             }         }         \/\/ \u0435\u0441\u043b\u0438 \u043d\u0435 collection         return generateResponseWrapper(body, wrapperClass, methodInformation);     }      \/**      * \u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0431\u0435\u0440\u0442\u043e\u043a \u0434\u043b\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 (\u0442\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u044c \u0441\u043f\u0438\u0441\u043a\u0430)      *      * @param bodyCollection \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c      * @param wrapperClass   \u043e\u0431\u044a\u0435\u043a\u0442 \u043e\u0431\u0435\u0440\u0442\u043a\u0438      * @return \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0431\u0435\u0440\u0442\u043e\u043a      *\/     @NonNull     private List&lt;Object&gt; generateListOfResponseWrapper(             @NonNull Collection&lt;?&gt; bodyCollection,             @NonNull Class&lt;? extends IWrapperModel&lt;?, ?&gt;&gt; wrapperClass,             @NonNull MethodInformation methodInformation     ) {         return bodyCollection.stream()                 .map((t) -&gt; t == null ?                         null :                         generateResponseWrapper(t, wrapperClass, methodInformation)                 )                 .collect(Collectors.toList());     }      \/**      * \u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u043e\u0431\u0435\u0440\u0442\u043a\u0443 \u0432\u043e\u043a\u0440\u0443\u0433 \u043e\u0431\u044a\u0435\u043a\u0442\u0430      *      * @param body         \u043e\u0431\u044a\u0435\u043a\u0442 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432 \u043e\u0431\u0435\u0440\u0442\u043a\u0443      * @param wrapperClass \u043e\u0431\u044a\u0435\u043a\u0442 \u043e\u0431\u0435\u0440\u0442\u043a\u0438      * @return \u043e\u0431\u0435\u0440\u0442\u043a\u0430      *\/     @NonNull     @SneakyThrows     private IWrapperModel&lt;?, ?&gt; generateResponseWrapper(             @NonNull Object body,             @NonNull Class&lt;? extends IWrapperModel&lt;?, ?&gt;&gt; wrapperClass,             @NonNull MethodInformation methodInformation     ) {         \/\/ wrapperClass \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u0435\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0431\u0435\u0437 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 - \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 IWrapperModel         IWrapperModel&lt;?, ?&gt; wrapper = wrapperClass.getDeclaredConstructor().newInstance();         wrapper.setBodyHelper(body, methodInformation);         wrapper.setDataHelper(wrapperServiceMap.get(wrapperClass).getDataHelper(body), methodInformation);         return wrapper;     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0412 \u043a\u043e\u0434\u0435 \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u043d\u0435\u0440\u0435\u0448\u0435\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043e\u0434\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0434\u043b\u044f \u0440\u0430\u0437\u043d\u044b\u0445 \u043e\u0431\u0435\u0440\u0442\u043e\u043a, \u0447\u0442\u043e \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e, \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0430\u043c \u0441\u0430\u043c\u0438\u043c. \u041c\u043d\u0435 \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u044d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0440\u0435\u0434\u043a\u0438\u0439 \u043a\u0435\u0439\u0441 \u0438 \u043d\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0435\u0433\u043e \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<p>\u0410 \u0442\u0430\u043a\u0436\u0435 \u0438\u043d\u0436\u0435\u043a\u0442 \u043c\u0430\u043f\u044b \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u0434\u0443\u043c\u0430\u044e, \u044f \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u044e \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0441\u0442\u0430\u0442\u044c\u044f\u0445.<\/p>\n<p>\u0412\u043e\u0442 \u0438 \u0432\u0441\u0435. \u041e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448 \u0441\u0442\u0430\u0440\u0442\u0435\u0440.<\/p>\n<p><strong>\u041a\u043e\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 BeanPostProcessor: <\/strong><a href=\"https:\/\/github.com\/Emilikan\/ResponseWrapperLib\/tree\/many-services-inject-through-map-with-bpp\" rel=\"noopener noreferrer nofollow\"><strong>GitHub<\/strong><\/a><\/p>\n<h2>\u0414\u0435\u043c\u043e<\/h2>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0432 \u0434\u0435\u043c\u043e \u043f\u0440\u043e\u0435\u043a\u0442:<\/p>\n<details class=\"spoiler\">\n<summary>Passport &#8212; \u043a\u043b\u0430\u0441\u0441 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@Data @AllArgsConstructor @NoArgsConstructor public class Passport {     private String series;     private String number; }<\/code><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>Wrapper &#8212; \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 generic-\u0438<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@Data @AllArgsConstructor @NoArgsConstructor public class Wrapper implements IWrapperModel&lt;MainModel, String&gt; {     @JsonUnwrapped     MainModel main;      String someInfo;      @Override     public void setBody(@NonNull MainModel body, @NonNull MethodInformation methodInformation) {         main = body;     }      @Override     public void setData(String data, @NonNull MethodInformation methodInformation) {         someInfo = data;     }      \t\/\/ \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c toString, hashCode, equals }<\/code><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>Wrapper2 &#8212; \u0432\u0442\u043e\u0440\u043e\u0439 \u043a\u043b\u0430\u0441\u0441-\u043e\u0431\u0435\u0440\u0442\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@Data @AllArgsConstructor @NoArgsConstructor public class Wrapper2 implements IWrapperModel&lt;MainModel, Passport&gt; {     @JsonUnwrapped     MainModel main;      Passport passport;      @Override     public void setData(Passport passport, @NonNull MethodInformation methodInformation) {         this.passport = passport;     }      @Override     public void setBody(@NonNull MainModel body, @NonNull MethodInformation methodInformation) {         this.main = body;     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>Wrapper2ServiceImpl &#8212; \u0432\u0442\u043e\u0440\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@WrapperService(wrapperModel = Wrapper2.class) public class Wrapper2ServiceImpl implements IWrapperService&lt;MainModel, Passport&gt; {      @Override     public Passport getData(@NonNull MainModel body) {         return new Passport(\"series\", \"number\");     }    }<\/code><\/pre>\n<p><em>WrapperServiceImpl<\/em> \u043e\u0441\u0442\u0430\u043b\u0441\u044f \u0438\u0437 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u0441 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u043c\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c\u0438<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>Controller2 &#8212; \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0434\u043b\u044f \u0432\u0442\u043e\u0440\u043e\u0439 \u043e\u0431\u0435\u0440\u0442\u043a\u0438<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@EnableResponseWrapper(wrapperClass = Wrapper2.class) @RequestMapping(\"\/test2\") public class Controller2 {      @GetMapping     public MainModel test() {         return new MainModel(\"Name\", \"Surname\");     }      @GetMapping(\"\/collection\")     public Collection&lt;MainModel&gt; testList() {         Collection&lt;MainModel&gt; mainModels = new ArrayList&lt;&gt;();         mainModels.add(new MainModel(\"Name1\", \"Surname1\"));         mainModels.add(new MainModel(\"Name2\", \"Surname2\"));          return mainModels;     }      @DisableResponseWrapper     @GetMapping(\"\/unwrapped\")     public MainModel unwrapped() {         return new MainModel(\"Name\", \"Surname\");     }  }<\/code><\/pre>\n<p><em>Controller<\/em> \u043e\u0441\u0442\u0430\u043b\u0441\u044f \u0442\u0430\u043a\u0438\u043c \u0436\u0435, \u043a\u0430\u043a \u0438 \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432 Postman<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d25\/446\/9f3\/d254469f38747914801d8bc26fe96ed4.png\" alt=\"\u0422\u0435\u0441\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 1 \u0441 \u043e\u0431\u0435\u0440\u0442\u043a\u043e\u0439 Wrapper\" title=\"\u0422\u0435\u0441\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 1 \u0441 \u043e\u0431\u0435\u0440\u0442\u043a\u043e\u0439 Wrapper\" width=\"1350\" height=\"1010\"><figcaption>\u0422\u0435\u0441\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 1 \u0441 \u043e\u0431\u0435\u0440\u0442\u043a\u043e\u0439 Wrapper<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/81e\/c74\/f9b\/81ec74f9b844f4cec959c2828cbd9e2a.png\" alt=\"\u0422\u0435\u0441\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 1 \u0441 \u043e\u0431\u0435\u0440\u0442\u043a\u043e\u0439 Wrapper \u0434\u043b\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438\" title=\"\u0422\u0435\u0441\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 1 \u0441 \u043e\u0431\u0435\u0440\u0442\u043a\u043e\u0439 Wrapper \u0434\u043b\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438\" width=\"1350\" height=\"1232\"><figcaption>\u0422\u0435\u0441\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 1 \u0441 \u043e\u0431\u0435\u0440\u0442\u043a\u043e\u0439 Wrapper \u0434\u043b\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5c2\/798\/0c7\/5c27980c7320cd01e4c5b1d65edd8d61.png\" alt=\"\u0422\u0435\u0441\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 2 \u0441 \u043e\u0431\u0435\u0440\u0442\u043a\u043e\u0439 Wrapper2\" title=\"\u0422\u0435\u0441\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 2 \u0441 \u043e\u0431\u0435\u0440\u0442\u043a\u043e\u0439 Wrapper2\" width=\"1350\" height=\"1076\"><figcaption>\u0422\u0435\u0441\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 2 \u0441 \u043e\u0431\u0435\u0440\u0442\u043a\u043e\u0439 Wrapper2<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/087\/071\/288\/087071288989e4f50d4ebd44ad01248d.png\" alt=\"\u0422\u0435\u0441\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 2 \u0441 \u043e\u0431\u0435\u0440\u0442\u043a\u043e\u0439 Wrapper2 \u0434\u043b\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439\" title=\"\u0422\u0435\u0441\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 2 \u0441 \u043e\u0431\u0435\u0440\u0442\u043a\u043e\u0439 Wrapper2 \u0434\u043b\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439\" width=\"1350\" height=\"1420\"><figcaption>\u0422\u0435\u0441\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 2 \u0441 \u043e\u0431\u0435\u0440\u0442\u043a\u043e\u0439 Wrapper2 \u0434\u043b\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439<\/figcaption><\/figure>\n<\/div>\n<\/details>\n<h2>\u0418\u0442\u043e\u0433<\/h2>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0441\u0442\u0430\u0440\u0442\u0435\u0440\u0430 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 BeanPostProcessor \u0438 \u0442\u043e, \u043a\u0430\u043a\u0438\u0435 \u0432\u0435\u0449\u0438 \u0441 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u043e\u0436\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c.<\/p>\n<p>\u041d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 spring \u043c\u043e\u0436\u0435\u0442 \u0434\u0430\u0442\u044c \u043d\u0430\u043c \u0442\u043e, \u0447\u0435\u0433\u043e \u043c\u044b \u0445\u043e\u0442\u0438\u043c, \u043d\u043e \u0447\u0430\u0441\u0442\u043e, \u0435\u0441\u043b\u0438 \u043d\u0430\u0441 \u0447\u0442\u043e-\u0442\u043e \u043d\u0435 \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442, \u0442\u043e \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u044c spring.<\/p>\n<p><strong>\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0430: <\/strong><a href=\"https:\/\/github.com\/Emilikan\/ResponseWrapperLib\" rel=\"noopener noreferrer nofollow\"><strong>GitHub<\/strong><\/a><\/p>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/568344\/\"> https:\/\/habr.com\/ru\/post\/568344\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<h2>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442, \u0434\u0440\u0443\u0437\u044c\u044f! \u042d\u0442\u043e \u0432\u0442\u043e\u0440\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u0440\u043e \u043e\u0431\u0435\u0440\u0442\u043a\u0443 \u043e\u0442\u0432\u0435\u0442\u043e\u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u043e \u0442\u043e, \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c BeanPostProcessor \u0438 \u0434\u043b\u044f \u0447\u0435\u0433\u043e \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0443\u0436\u043d\u043e &#8212; \u044d\u0442\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u043e\u0441\u044b\u043b \u0441\u0442\u0430\u0442\u044c\u0438. \u0421\u0434\u0435\u043b\u0430\u0435\u043c \u043c\u044b \u044d\u0442\u043e \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0432 \u043f\u0440\u043e\u0435\u043a\u0442 \u0438\u0437 <a href=\"https:\/\/habr.com\/ru\/post\/567056\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438<\/a>.&nbsp;<\/p>\n<p>\u041f\u043e\u0434 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0441 \u043d\u0438\u043a\u043e\u043c <a class=\"mention\" href=\"\/users\/maxzh83\">@maxzh83<\/a> \u0443\u043a\u0430\u0437\u0430\u043b \u043d\u0430 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u043d\u0435\u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 &#8212; \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u0441\u0435\u0440\u0432\u0438\u0441 IWrapperService, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0438\u0437-\u0437\u0430 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0438\u0434\u0435\u0442 \u0438\u043d\u0436\u0435\u043a\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430.<\/p>\n<pre><code class=\"java\">private final IWrapperService wrapperService;<\/code><\/pre>\n<p>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0442\u043e, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0448\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u043d\u0435\u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0441\u043f\u0440\u0438\u043d\u0433\u0430 &#8212; \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439. \u0418 \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0441\u043f\u0440\u0438\u043d\u0433\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e BeanPostProcessor \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438.<\/p>\n<h2>\u0412\u0441\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u043c, \u0447\u0442\u043e \u0433\u043e\u0442\u043e\u0432\u043e \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442<\/h2>\n<p>\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u0442\u044c, \u0447\u0442\u043e \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0432 <a href=\"https:\/\/habr.com\/ru\/post\/567056\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a>. \u041a\u043e\u0434 \u043d\u0430 <a href=\"https:\/\/github.com\/Emilikan\/ResponseWrapperLib\/tree\/master\" rel=\"noopener noreferrer nofollow\">GitHub \u043d\u0430 \u0432\u0435\u0442\u043a\u0435 master<\/a>.<\/p>\n<details class=\"spoiler\">\n<summary>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e \u0442\u043e, \u0447\u0442\u043e \u0443\u0436\u0435 \u0431\u044b\u043b\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u043e<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0441\u0442\u0430\u0440\u0442\u0435\u0440, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 2 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438: <em>@DisableResponseWrapper<\/em> \u0438 <em>@EnableResponseWrapper<\/em>, \u0430 \u0442\u0430\u043a\u0436\u0435 2 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430: <em>IWrapperModel<\/em> \u0438 <em>IWrapperService<\/em>, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043e\u0442\u0432\u0435\u0442\u044b \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u0432 \u043d\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441.<\/p>\n<p>\u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0430\u043a\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430, \u0432 \u0441\u0442\u0430\u0440\u0442\u0435\u0440\u0435 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u043a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <em>ResponseBodyAdvice&lt;Object&gt;<\/em> \u0438 \u0430\u043d\u043d\u043e\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>@ControllerAdvice(annotations = EnableResponseWrapper.class)<\/code><\/p>\n<pre><code class=\"java\">@AllArgsConstructor @ControllerAdvice(annotations = EnableResponseWrapper.class) public class ResponseWrapperAdvice implements ResponseBodyAdvice&lt;Object&gt; { \t... }<\/code><\/pre>\n<blockquote>\n<p>\u0410\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f <code>@ControllerAdvice(annotations = EnableResponseWrapper.class)<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u0447\u0442\u043e \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u0440\u0430\u0437\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u043c\u0438. \u0422\u0430\u043a\u0436\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u043d\u0430\u0448\u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u0431\u0443\u0434\u0443\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043c\u0435\u0447\u0435\u043d\u044b @EnableResponseWrapper.<\/p>\n<p>\u041a\u043b\u0430\u0441\u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <em>ResponseBodyAdvice&lt;&gt;<\/em>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043e\u0442\u0432\u0435\u0442, \u043f\u043e\u0441\u043b\u0435 \u0435\u0433\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u043c @ResponseBody \u0438\u043b\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u043c <em>ResponseEntity<\/em>, \u043d\u043e \u0434\u043e \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0442\u0435\u043b\u043e \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <em>HttpMessageConverter.<\/em><\/p>\n<\/blockquote>\n<p>\u0412 \u043a\u043b\u0430\u0441\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0431\u044b\u043b\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c 2 \u043c\u0435\u0442\u043e\u0434\u0430:<\/p>\n<pre><code class=\"java\">public boolean supports(MethodParameter returnType, @NonNull Class converterType)<\/code><\/pre>\n<p>&#8212; \u043c\u0435\u0442\u043e\u0434 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u0432\u0445\u043e\u0434\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u043c \u043a \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 false &#8212; \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0442\u043e\u0447\u043a\u0438 \u0432\u0445\u043e\u0434\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442.<\/p>\n<pre><code class=\"java\">public Object beforeBodyWrite(@Nullable Object body, @NonNull MethodParameter returnType, @NonNull MediaType selectedContentType, @NonNull Class selectedConverterType, @NonNull ServerHttpRequest request, @NonNull ServerHttpResponse response)<\/code><\/pre>\n<p>&#8212; \u043c\u0435\u0442\u043e\u0434 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0442\u043e\u0447\u043a\u0438 \u0432\u0445\u043e\u0434\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430. \u0412\u0435\u0440\u043d\u0443\u0442\u044c \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d api.<\/p>\n<p>\u042d\u0442\u043e\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043c\u044b \u043f\u043e\u043b\u043e\u0436\u0438\u043b\u0438 \u0432 \u0441\u0442\u0430\u0440\u0442\u0435\u0440 \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u0434\u0435\u043c\u043e-\u043f\u0440\u043e\u0435\u043a\u0442 \u043f\u043e\u0434 \u0434\u0430\u043d\u043d\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b.<\/p>\n<blockquote>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438 \u0434\u043b\u044f \u0438\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0441 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u043e\u0442\u0432\u0435\u0442\u043e\u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432. \u041f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u0445. (\u0425\u043e\u0440\u043e\u0448\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043e\u0431 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 <a href=\"https:\/\/habr.com\/ru\/post\/528116\/\" rel=\"noopener noreferrer nofollow\">https:\/\/habr.com\/ru\/post\/528116\/<\/a>)<\/p>\n<p>\u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f ControllerAdvice+ResponseBodyAdvice \u0438 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0439 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0431\u043e\u043b\u0435\u0435 \u0433\u0438\u0431\u043a\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043b\u044e\u0431\u044b\u0445 \u043e\u0442\u0432\u0435\u0442\u043e\u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043c\u0435\u0442\u043e\u0434\u0435, \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0435, \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u0438 \u043e\u0442\u0432\u0435\u0442\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430.<\/p>\n<\/blockquote>\n<\/div>\n<\/details>\n<h2>\u0412\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438<\/h2>\n<p>\u041c\u044b \u0445\u043e\u0442\u0438\u043c \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430-\u043e\u0431\u0435\u0440\u0442\u043a\u0438 \u0441\u0432\u043e\u0439 \u0441\u0435\u0440\u0432\u0438\u0441.&nbsp;<\/p>\n<p>\u0421\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438 \u0431\u044b\u0441\u0442\u0440\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 &#8212; \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u0435\u043c, \u0447\u0442\u043e \u0443\u0436\u0435 \u0443\u043c\u0435\u0435\u0442 spring &#8212; \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439.&nbsp;<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432:<\/p>\n<pre><code class=\"java\">@Service @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface WrapperService {     Class&lt;? extends IWrapperModel&lt;?, ?&gt;&gt; wrapperModel(); }<\/code><\/pre>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u043d\u0430\u0448\u0430 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u0432\u0438\u0441\u0438\u0442 \u043d\u0430\u0434 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c &#8212; \u0442\u043e \u0432\u0435\u0448\u0430\u0435\u043c \u043d\u0430\u0434 \u043d\u0430\u0448\u0435\u0439 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0435\u0439 <em>@Service<\/em> &#8212; \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <em>@WrapperService<\/em> \u0432\u043c\u0435\u0441\u0442\u043e <em>@Service.<\/em><\/p>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c-\u043e\u0431\u0435\u0440\u0442\u043a\u0443 \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u043e \u043d\u0435\u0439 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430.<\/p>\n<h2>\u041d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0438<\/h2>\n<p>\u0421\u0440\u0430\u0437\u0443 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u0442\u0430\u0440\u0442\u0435\u0440 \u0431\u044b\u043b \u0431\u043e\u043b\u0435\u0435 \u0433\u0438\u0431\u043a\u0438\u043c.<\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c generic-\u0438. \u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043c\u043e\u0434\u0435\u043b\u0438:<\/p>\n<pre><code class=\"java\">public interface IWrapperModel&lt;Body, Data&gt; {         void setData(@Nullable Data data, @NonNull MethodInformation methodInformation);      default &lt;DataHelper&gt; void setDataHelper(@Nullable DataHelper data, @NonNull MethodInformation methodInformation){         @SuppressWarnings(\"unchecked\")         Data data1 = (Data) data;          setData(data1, methodInformation);     }      void setBody(@NonNull Body body, @NonNull MethodInformation methodInformation);      default &lt;BodyHelper&gt; void setBodyHelper(@NonNull BodyHelper body, @NonNull MethodInformation methodInformation) {         @SuppressWarnings(\"unchecked\")         Body body1 = (Body) body;          setBody(body1, methodInformation);     } }<\/code><\/pre>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u0445\u0435\u043b\u043f\u0435\u0440\u044b setBodyHelper \u0438 setDataHelper \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 Wildcard. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e helper-\u043c\u0435\u0442\u043e\u0434\u044b \u0438 \u0437\u0430\u0447\u0435\u043c \u043e\u043d\u0438 \u043d\u0443\u0436\u043d\u044b \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0435\u0441\u0442\u044c \u0432 <a href=\"https:\/\/docs.oracle.com\/javase\/tutorial\/java\/generics\/capture.html\" rel=\"noopener noreferrer nofollow\">\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a>.<\/p>\n<p>\u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0434\u0435\u043b\u0430\u0435\u043c \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430:<\/p>\n<pre><code class=\"java\">public interface IWrapperService&lt;Body, Data&gt; {     @Nullable     Data getData(@NonNull Body body);      default &lt;BodyHelper&gt; Data getDataHelper (@NonNull BodyHelper body) {         @SuppressWarnings(\"unchecked\")         Body body1 = (Body) body;          return getData(body1);     } }<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u043e\u0431\u0435\u0440\u0442\u043a\u0443 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0435, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0441 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<pre><code class=\"java\">@Getter @AllArgsConstructor public class MethodInformation {     @NonNull     private final MethodParameter returnType;     @NonNull     private final MediaType selectedContentType;     @NonNull     private final Class&lt;?&gt; selectedConverterType;     @NonNull     private final ServerHttpRequest request;     @NonNull     private final ServerHttpResponse response; } <\/code><\/pre>\n<h2>\u0418\u0437\u043c\u0435\u043d\u044f\u0435\u043c ResponseWrapperAdvice<\/h2>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0435, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c &#8212; \u044d\u0442\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0438\u043d\u0436\u0435\u043a\u0442 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 <em>ResponseWrapperAdvice.<\/em><\/p>\n<p>\u0412\u043c\u0435\u0441\u0442\u043e:<\/p>\n<pre><code class=\"java\">private final IWrapperService wrapperService;<\/code><\/pre>\n<p>\u041f\u0438\u0448\u0435\u043c:<\/p>\n<pre><code class=\"java\">private final List&lt;IWrapperService&lt;?, ?&gt;&gt; wrapperServiceList;<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c spring \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430\u0439\u0434\u0435\u0442 \u0438 \u0441\u043e\u0431\u0435\u0440\u0435\u0442 \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0435 \u043a\u043b\u0430\u0441\u0441\u044b, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0435 <em>IWrapperService<\/em> \u0441 \u043b\u044e\u0431\u044b\u043c\u0438 <em>Body<\/em> \u0438 <em>Data.<\/em><\/p>\n<p>\u041d\u0430\u043f\u0438\u0448\u0435\u043c \u043c\u0435\u0442\u043e\u0434 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 \u0442\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u043d\u0430\u0448\u0435\u043c\u0443 \u043a\u043b\u0430\u0441\u0441\u0443-\u043e\u0431\u0435\u0440\u0442\u043a\u0435.<\/p>\n<pre><code class=\"java\">... @NonNull private IWrapperService&lt;?, ?&gt; getWrapperService( \t\t@NonNull Class&lt;? extends IWrapperModel&lt;?, ?&gt;&gt; wrapperClass ) { \t\tIWrapperService&lt;?, ?&gt; wrapperService = null;  \t\tfor (IWrapperService&lt;?, ?&gt; iWrapperService : wrapperServiceList) { \t\t\t\tfor (Annotation annotation : iWrapperService.getClass().getAnnotations()) { \t\t\t\t\t\tif (annotation.annotationType() == WrapperService.class &amp;&amp; \t\t\t\t\t\t\t\t((WrapperService) annotation).wrapperModel()==wrapperClass \t\t\t\t\t\t){ \t\t\t\t\t\t\t\twrapperService = iWrapperService; \t\t\t\t\t\t\t\tbreak; \t\t\t\t\t\t} \t\t\t\t} \t\t}  \t\tif (wrapperService==null) { \t\t\t\tthrow new RuntimeException(\"\u041e\u0431\u0435\u0440\u0442\u043a\u0430 \u0431\u0435\u0437 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\"); \t\t} \t\treturn wrapperService; } ...<\/code><\/pre>\n<p>\u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>iWrapperService.getClass().getAnnotations()<\/code> \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0438 \u0438\u0449\u0435\u043c \u0441\u0440\u0435\u0434\u0438 \u043d\u0438\u0445 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e <em>@WrapperService<\/em>. \u0418\u0437 \u043d\u0435\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u043b\u0430\u0441\u0441-\u043e\u0431\u0435\u0440\u0442\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c \u0441 \u0442\u043e\u0439, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0441\u0435\u0439\u0447\u0430\u0441 \u0441\u0430\u043c\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@AllArgsConstructor @ControllerAdvice(annotations = EnableResponseWrapper.class) public class ResponseWrapperAdvice implements ResponseBodyAdvice&lt;Object&gt; {      private final List&lt;IWrapperService&lt;?, ?&gt;&gt; wrapperServiceList;      \/**      * \u041c\u0435\u0442\u043e\u0434 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d, \u0435\u0441\u043b\u0438 \u043f\u043e\u043c\u0435\u0447\u0435\u043d \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0435\u0439 {@link DisableResponseWrapper} &lt;br\/&gt; &lt;br\/&gt;      *      * @param returnType    the return type      * @param converterType the selected converter type      * @return {@code true} if {@link #beforeBodyWrite} should be invoked;      * {@code false} otherwise      *\/     @Override     public boolean supports(MethodParameter returnType, @NonNull Class converterType) {         for (Annotation a : returnType.getMethodAnnotations()) {             if (a.annotationType() == DisableResponseWrapper.class) {                 return false;             }         }          return true;     }      \/**      * \u041e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u043e\u0442\u0432\u0435\u0442      *      * @param body                  the body to be written      * @param returnType            the return type of the controller method      * @param selectedContentType   the content type selected through content negotiation      * @param selectedConverterType the converter type selected to write to the response      * @param request               the current request      * @param response              the current response      * @return the body that was passed in or a modified (possibly new) instance      *\/     @SneakyThrows     @Override     @Nullable     public Object beforeBodyWrite(             @Nullable Object body,             @NonNull MethodParameter returnType,             @NonNull MediaType selectedContentType,             @NonNull Class selectedConverterType,             @NonNull ServerHttpRequest request,             @NonNull ServerHttpResponse response     ) {         MethodInformation methodInformation = new MethodInformation(returnType, selectedContentType, selectedConverterType, request, response);          if (body == null) {             return null;         }          \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c wrapperClass \u0438\u0437 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438         Class&lt;? extends IWrapperModel&lt;?, ?&gt;&gt; wrapperClass = null;         for (Annotation annotation : returnType.getContainingClass().getAnnotations()) {             if (annotation.annotationType() == EnableResponseWrapper.class) {                 wrapperClass = ((EnableResponseWrapper) annotation).wrapperClass();                 break;             }         }          if (wrapperClass == null) {             return body;         }          \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0431\u044b\u043b \u043b\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u043d Collection \u0438\u043b\u0438 \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a Collection         if (Collection.class.isAssignableFrom(body.getClass())) {             try {                 Collection&lt;?&gt; bodyCollection = (Collection&lt;?&gt;) body;                 <\/code><\/pre>\n<\/div>\n<\/details>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-326622","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/326622","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=326622"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/326622\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=326622"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=326622"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=326622"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}