HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-03-10
1 <p>Теги: java, invocationhandler, personrepository, proxy, method, args, лямбда-выражение, логика обработки вызовов всех методов, retrofit, spring data jpa, сигнатура метода, boilerplate code, java reflection api, java.lang.reflect.proxy, динамический прокси-объект</p>
1 <p>Теги: java, invocationhandler, personrepository, proxy, method, args, лямбда-выражение, логика обработки вызовов всех методов, retrofit, spring data jpa, сигнатура метода, boilerplate code, java reflection api, java.lang.reflect.proxy, динамический прокси-объект</p>
2 <p>Тоже впечатлены элегантностью работы с<a>Retrofit</a>и<a>Spring Data JPA</a>? Когда вы просто добавляете в интерфейс сигнатуру метода, а при вызове этого метода оказывается, что он реально работает!</p>
2 <p>Тоже впечатлены элегантностью работы с<a>Retrofit</a>и<a>Spring Data JPA</a>? Когда вы просто добавляете в интерфейс сигнатуру метода, а при вызове этого метода оказывается, что он реально работает!</p>
3 <h2>Да, долой boilerplate* code!</h2>
3 <h2>Да, долой boilerplate* code!</h2>
4 <p>Так это выглядит при работе с Spring Data JPA. И никаких SQL, HQL или JPQL!</p>
4 <p>Так это выглядит при работе с Spring Data JPA. И никаких SQL, HQL или JPQL!</p>
5 interface PersonRepository extends Repository&lt;Person, Long&gt; { List&lt;Person&gt; findByLastname(String lastname); Long countByLastname(String lastname); }<p>Знаете что там внутри? Ничего нового - обычный Java Reflection API!</p>
5 interface PersonRepository extends Repository&lt;Person, Long&gt; { List&lt;Person&gt; findByLastname(String lastname); Long countByLastname(String lastname); }<p>Знаете что там внутри? Ничего нового - обычный Java Reflection API!</p>
6 <p>Когда библиотека получает ваш интерфейс, ей нужно решить два главных вопроса: 1. Как в процессе выполнения программы создать экземпляр класса, реализующий ваш интерфейс? Ведь библиотека должна дать вам возможность вызова этих методов так, как будто это методы самого обычного класса. 2. Как получить и проанализировать сигнатуры методов, которые вы описали в интерфейсе? Ведь на основании соглашений о наименовании метода интерфейса библиотеке необходимо обработать вызов этого метода определённым способом.</p>
6 <p>Когда библиотека получает ваш интерфейс, ей нужно решить два главных вопроса: 1. Как в процессе выполнения программы создать экземпляр класса, реализующий ваш интерфейс? Ведь библиотека должна дать вам возможность вызова этих методов так, как будто это методы самого обычного класса. 2. Как получить и проанализировать сигнатуры методов, которые вы описали в интерфейсе? Ведь на основании соглашений о наименовании метода интерфейса библиотеке необходимо обработать вызов этого метода определённым способом.</p>
7 <p>Класс<a>java.lang.reflect.Proxy</a>создан как раз для этого. Он позволяет создать динамический прокси-объект, реализующий указанный интерфейс.</p>
7 <p>Класс<a>java.lang.reflect.Proxy</a>создан как раз для этого. Он позволяет создать динамический прокси-объект, реализующий указанный интерфейс.</p>
8 <p>В таком прокси-объекте все вызовы его методов перехватываются и направляются в специальный обработчик - реализацию интерфейса<a>InvocationHandler</a>.</p>
8 <p>В таком прокси-объекте все вызовы его методов перехватываются и направляются в специальный обработчик - реализацию интерфейса<a>InvocationHandler</a>.</p>
9 <h2>Вот как это выглядит:</h2>
9 <h2>Вот как это выглядит:</h2>
10 PersonRepository personRepository = (PersonRepository) Proxy.newProxyInstance(PersonRepository.class.getClassLoader(), new Class[] { PersonRepository.class }, (proxy, method, args) -&gt; { String methodName = method.getName(); // Обрабатываем вызов метода интерфейса, возвращаем результат if(methodName.startsWith("find")) { // ... } return new Object(); });<p>Лямбда-выражение (<strong>proxy, method, args</strong>) реализует интерфейс<strong>InvocationHandler</strong>и содержит логику обработки вызовов всех методов<strong>PersonRepository</strong>.</p>
10 PersonRepository personRepository = (PersonRepository) Proxy.newProxyInstance(PersonRepository.class.getClassLoader(), new Class[] { PersonRepository.class }, (proxy, method, args) -&gt; { String methodName = method.getName(); // Обрабатываем вызов метода интерфейса, возвращаем результат if(methodName.startsWith("find")) { // ... } return new Object(); });<p>Лямбда-выражение (<strong>proxy, method, args</strong>) реализует интерфейс<strong>InvocationHandler</strong>и содержит логику обработки вызовов всех методов<strong>PersonRepository</strong>.</p>
11 <p><strong>InvocationHandler</strong>содержит все необходимые для обработки вызова метаданные: - ссылку на объект, - метод которого вызвал пользователь, - сигнатуру вызванного метода с его названием, параметрами и аннотациями, - и, конечно, значения аргументов, переданных пользователем при вызове метода.</p>
11 <p><strong>InvocationHandler</strong>содержит все необходимые для обработки вызова метаданные: - ссылку на объект, - метод которого вызвал пользователь, - сигнатуру вызванного метода с его названием, параметрами и аннотациями, - и, конечно, значения аргументов, переданных пользователем при вызове метода.</p>
12 <p>В использовании полученный прокси-объект не отличается от обыкновенного класса:</p>
12 <p>В использовании полученный прокси-объект не отличается от обыкновенного класса:</p>
13 List&lt;Person&gt; persons = personRepository.findByLastname("Otus");<p><em>Есть вопрос? Напишите в комментариях!</em>*<a>Boilerplate_code</a></p>
13 List&lt;Person&gt; persons = personRepository.findByLastname("Otus");<p><em>Есть вопрос? Напишите в комментариях!</em>*<a>Boilerplate_code</a></p>
14  
14