Как перехватить JdbcTemplate, экземпляр которого создан мной - PullRequest
1 голос
/ 08 октября 2019

Я хочу собрать статистические значения БД после любого выполнения DQL ("SELECT ...") или DML (INSERT / UPDATE / DELETE ...)для текущего сеанса.
Текущий, я использовал Spring AOP для достижения этого следующим образом:

@Aspect
@Component
public class StatisticalValueCollector {
    @After("execution(* org.springframework.jdbc.core..*JdbcOperations.*(String, ..))")
    public void collectStatisTicalValues(JoinPoint jp) {
        //Collect DB statistical values
    }
 }

Он отлично работает как для JdbcTemplate, так и NamedParameterJdbcTemplate, аннотированных @Autowired, но когда я сам создаю их экземпляр ㄋ, он не работает.

Сработавший пример:

@Autowired
JdbcTemplate jdbcTemplate;
...
List<Map<String, Object>> result = jdbcTemplate.queryForList("SELECT ...");

Неработающий пример:

DriverManagerDatasource ds = new DriverManagerDatasource();
...
JdbcTemplate jdbcTemplate = new JdbcTemplate (ds);
List<Map<String, Object>> result = jdbcTemplate.queryForList("SELECT ...");

Насколько я знаю, кажется, что если JdbcTemplate создан Spring, он может быть прокси-сервер в соответствии с этим постом - AOP: возможность перехвата JDBCTemplateзвонки но не NamedParameterJdbcTemplate звонки .

Поэтому мой вопрос: " Как перехватить JdbcTemplate или NamedParameterJdbcTemplate, созданный мной? ";
Буду весьма признателен за любые советы и предложения. Спасибо!

ОБНОВЛЕНИЕ
Я также рассмотрел различные подходы, такие как p6spy и datasource-proxy , похоже, единственное решение состоит в использовании чистого AspectJ или что-то еще?

Ответы [ 2 ]

1 голос
/ 08 октября 2019

Если в обоих случаях вы печатаете свой экземпляр шаблона JDBC следующим образом

System.out.println(jdbcTemplate + "\n  " + jdbcTemplate.getClass());

, то для созданного вами самостоятельно вы увидите

org.springframework.jdbc.core.JdbcTemplate@3c71cf3e
  class org.springframework.jdbc.core.JdbcTemplate

, а для автоматического вводаодин вы увидите

org.springframework.jdbc.core.JdbcTemplate@8f39224
  class org.springframework.jdbc.core.JdbcTemplate$$EnhancerBySpringCGLIB$$59a5407f

Найдите разницу? Для последнего Spring создает динамический прокси, если существует целевой аспект. Только при наличии динамического прокси у Spring AOP есть что зарегистрировать свои советы по аспектам.

Я не пользователь Spring, поэтому я не знаю, существует ли другой канонический способ создания шаблонов JDBC, для которого автоматическидинамический прокси создается по требованию. Поэтому, если вы не хотите вручную создать прокси (что возможно, но излишне сложно) или не найдете другого способа сделать это, просто используйте внедрение зависимостей (DI) и автоматическое подключение. Не в этом ли смысл использования Spring в первую очередь? Создание зависимостей, которые вы можете получить, является своего рода анти-шаблоном для контейнера DI, такого как Spring.

Если вы настаиваете на своем неортодоксальном и трудном для тестирования (как внедрить макет для локальной переменной, вы вызываете конструкторна подходе?), вы всегда можете использовать полный AspectJ в качестве альтернативы Spring AOP. Но я сомневаюсь, что в этой ситуации оно того стоит.

0 голосов
/ 08 октября 2019

В классе, помеченном @Configuration, определите JdbcTemplate как @Bean:

@Configuration
public class JdbcConfiguration {

    private DriverManagerDatasource ds = new DriverManagerDatasource();

    @Bean
    public JdbcTemplate jdbcTemplate() {
        return new JdbcTemplate(ds);
    }
}

Таким образом, вы разрешите Spring прокси-сервер с AOP при перехвате в @Aspect, поместив ваш JdbcTemplate боб в ApplicationContext. Теперь вы можете автоматически связать его с:

@Autowired private JdbcTemplate jdbcTemplate;
...