Помогите с BeanPostProcessor, не отрабатывает

102
17 февраля 2021, 15:20

Всем привет. Столкнулся с такой проблемой: Написал свой BeanPostProcessor для того, чтобы все методы, которые помечены моей аннотацией @Timing, выводил в консоль время их выполнения.

Использую SpringBoot.

Мой BeanPostProcessor выглядит следующим образом:

import com.example.version2.annotation.Timing;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
@Component
public class TimingBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        Class type = bean.getClass();
        Method[] methods = type.getMethods();
        for (Method method : methods) {
            if (method.isAnnotationPresent(Timing.class)) {
                Object proxy = Proxy.newProxyInstance(type.getClassLoader(),type.getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        long before = System.nanoTime();
                        Object retVal = method.invoke(bean, args);
                        long after = System.nanoTime();
                        System.out.println("Method worked: " + (after - before) + " nano seconds");
                        return retVal;
                    }
                });
                return proxy;
            } else {
                return bean;
            }
        }
         return bean;
    }
    @Override
    public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
        return bean;
    }
}

И собственно моя аннотация:

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Timing {
}

Вешаю аннотацию над одним из методов в dao классе:

@Timing
public  List<Map<String, Object>> selectQuery() {
    String selectQuery = prop.getMYSQL_SELECT();
    return mysqlTemplate.queryForList(selectQuery);
}

При старте приложения проблем нет, выполняю запрос, но в консоли ничего не вижу. Вроде бы сам BeanPostProcessor написал верно. Не могу найти в чем ошибка. Подскажите пожалуйста.

Также хотелось бы узнать, как мне эту информацию о времени выполнении метода передать на фронтенд в json или каком-нибудь List (не принципиально).

Буду очень благодарен за подсказку. Спасибо.

Answer 1

создавайте один прокси для всех методов, иначе на первом же методе без аннотации постпроцессор вернет не проксированный бин: 1. смотрите, наличие аннотации хоть у одного метода 2. создаете прокси на бин 3. внутри invoke проверяете у метода наличие аннотации

READ ALSO
Получить доступ к переменной из класса наследника

Получить доступ к переменной из класса наследника

Мне нужно записать переменную page из класса bumaga в массив All чтобы потом её вывестиКак это сделать с помощью get и set?

129
Возможно ли boolean перевести в int

Возможно ли boolean перевести в int

Возможно ли boolean перевести в int для сортировки с помощью Comparable

102
Scheduled tasks в java

Scheduled tasks в java

Есть SpringBoot app, и есть задача: организувать список задач которые будут запускаться в определенное время

137
Synchronized-блок Java

Synchronized-блок Java

Есть два класса

103