Spring Proxy
Spring proxy — объект-обёртка, через который контейнер перехватывает вызов метода и применяет advice: транзакцию, безопасность, кэширование или пользовательский аспект.
caller → proxy → interceptor chain → target methodВиды
- JDK dynamic proxy реализует интерфейсы целевого объекта;
- class-based proxy создаёт подкласс и может проксировать класс без интерфейса.
Конкретный выбор зависит от конфигурации и возможностей класса. final-класс или final-метод нельзя переопределить class-based proxy. Приватный метод не является внешней точкой вызова.
Self-invocation
public void importAll() {
saveOne(); // вызов через this, proxy не участвует
}
@Transactional
public void saveOne() {}Аннотация на saveOne не создаст новую interceptor-границу при таком вызове. Решения:
- вынести операцию в другой bean;
- перенести аннотацию на внешнюю точку;
- использовать программный API;
- применять weaving только при осознанной необходимости.
Идентичность и тип
Инъекция обычно получает proxy, а не target. Проверка точного класса, прямой new и нестандартный equals могут дать сюрпризы. Объект, созданный вручную, контейнером не проксируется.
Вопросы для повторения
- Где выполняется
@Transactional? В interceptor proxy вокруг внешнего вызова. - Почему вызов через
thisобходится без advice? Он не проходит через proxy-ссылку. - Чем JDK proxy отличается от class proxy? Первый реализует интерфейс, второй наследует класс.
- Можно ли проксировать private-метод? Не обычным Spring proxy.
- Почему
new Service()не даёт транзакций? Такой объект не создан и не обёрнут контейнером.
Связано: Spring AOP, Transactional, Аннотация Cacheable.