Почему Spring успешно перехватывает вызовы функций внутри класса в классе @Configuration, но не в обычном бине?

Недавно я заметил, что Spring успешно перехватывает вызовы функций внутри класса в классе @Configuration, но не в обычном компоненте.

Звонок как это

@Repository
public class CustomerDAO {  
    @Transactional(value=TxType.REQUIRED)
    public void saveCustomer() {
        // some DB stuff here...
        saveCustomer2();
    }
    @Transactional(value=TxType.REQUIRES_NEW)
    public void saveCustomer2() {
        // more DB stuff here
    }
}

не удается запустить новую транзакцию, потому что, хотя код saveCustomer () выполняется в прокси-сервере CustomerDAO, код saveCustomer2 () выполняется в развернутом классе CustomerDAO, как я могу видеть, посмотрев «this» в отладчике, и так Spring не имеет возможности перехватить вызов saveCustomer2.

Однако в следующем примере, когда транзакцияManager () вызывает метод createDataSource (), он корректно перехватывается и вызывает метод createDataSource () прокси-сервера, а не развернутого класса, о чем свидетельствует поиск этого элемента в отладчике.

@Configuration
public class PersistenceJPAConfig {
    @Bean
    public DriverManagerDataSource createDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        //dataSource.set ... DB stuff here
        return dataSource;
    }

   @Bean 
       public PlatformTransactionManager transactionManager(   ){
           DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(createDataSource());
           return transactionManager;
       }
}

Поэтому мой вопрос заключается в том, почему Spring может правильно перехватывать вызовы функций внутри класса во втором примере, а не в первом. Используются ли разные типы динамических прокси?

Всего 2 ответа


Spring использует прокси для вызова метода, и когда вы используете это ... он обходит этот прокси. Для аннотаций @Bean Spring использует отражение, чтобы найти их.


прочитайте немного весеннего исходного кода. Я пытаюсь ответить на это.

@Configuration том, как весной справиться с @Configuration . в ConfigurationClassPostProcessor, который является BeanFactoryPostProcessor, он улучшит все ConfigurationClasses и создаст Enhancer в качестве подкласса. этот Enhancer регистрирует два ЗВОНОКА (BeanMethodInterceptor, BeanFactoryAwareMethodInterceptor). Вы вызываете метод PersistenceJPAConfig который будет проходить через ЗВОНОКИ. в BeanMethodInterceptor он получает бин из контейнера Spring.

это может быть не ясно. Вы можете увидеть исходный код в ConfigurationClassEnhancer.java BeanMethodInterceptor . ConfigurationClassPostProcessor.java enhanceConfigurationClasses


Есть идеи?

10000