Меня заинтересовало, как работает SpringTree @Transactional, но везде, где я читал об этом, есть концепция прокси. Предполагается, что прокси подключается автоматически вместо реального компонента и «украшает» базовый метод дополнительными методами обработки транзакций.
Теория мне понятна и имеет смысл, поэтому я попытался проверить, как она работает в действии.
Я создал приложение Spring Boot с базовым контроллером и служебными слоями и пометил один метод аннотацией @Transactional. Сервис выглядит так:
public class TestService implements ITestService {
@PersistenceContext
EntityManager entityManager;
@Transactional
public void doSomething() {
System.out.println("Service...");
entityManager.persist(new TestEntity("XYZ"));
}}
Контроллер вызывает сервис:
public class TestController {
@Autowired
ITestService testService;
@PostMapping("/doSomething")
public ResponseEntity addHero() {
testService.doSomething();
System.out.println(Proxy.isProxyClass(testService.getClass()));
System.out.println(testService);
return new ResponseEntity(HttpStatus.OK);
}}
Все работает, новая сущность сохраняется в БД, но весь вопрос, который меня беспокоит, - это вывод:
Service...
false
com.example.demo.TestService@7fb48179
Кажется, что класс обслуживания был введен явно вместо прокси-класса. Не только «isProxy» возвращает false, но и вывод класса («com.example.demo.TestService@7fb48179») предполагает, что он не является прокси.
Не могли бы вы помочь мне с этим? Почему не был введен прокси, и как он работает даже без прокси? Есть ли способ, которым я могу «заставить» его проксировать, и если это так - почему прокси-сервер не внедряется по умолчанию в Spring?
Добавлять особо нечего, это действительно простое приложение. Свойства приложения тоже ничего особенного:
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=superSecretPassword
spring.datasource.url=jdbc:mysql://localhost:3306/heroes?serverTimezone=UTC
spring.jpa.hibernate.ddl-auto=create-drop
Заранее спасибо!