@Cachable аннотация не работает

Мы используем ehcache для кэширования в нашем проекте.

import com.googlecode.ehcache.annotations.Cacheable;
// Other imports

@Component
public class Authenticator{
    @Cacheable(cacheName = "rest_client_authorized")
    public boolean isUserAuthorized(final String user, final String sessionId) {
        // Method code
    }
}

При входе в метод нет перехватчика кеша. То, что мы проверили до сих пор:

  1. Мы вызываем этот метод не внутри класса, а снаружи. Таким образом, проблема не во внутренних вызовах, которые заставляют обходить прокси.
  2. Мы добавили интерфейс для этого класса и изменили инъекции, в которых этот класс вызывается, чтобы использовать представление интерфейса вместо конкретного класса.

Мы определили диспетчер кеша в контексте нашего приложения следующим образом:

   <ehcache:annotation-driven cache-manager="ehCacheManager" />         
   <bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
       <!-- use a share singleton CacheManager -->
       <property name="shared" value="true" />
   </bean>

Кэш определяется следующим образом:

        <cache name="rest_client_authorized"
            eternal="false"
            maxElementsInMemory="50"
            overflowToDisk="false" diskPersistent="false"
            timeToIdleSeconds="0" timeToLiveSeconds="600"
            memoryStoreEvictionPolicy="LRU" />

Когда мы тестируем диспетчер кеша с помощью Jconsole, мы видим, что кеш *rest_auth_disabled* существует и пуст.

Любые идеи относительно того, почему это не работает, будут высоко оценены. Спасибо!

Обновления (агрегация из комментариев ниже):

==========================================**

Это устаревший код, который отлично работал с классом и определениями, которые я предоставил. Метод, о котором я говорю здесь, является новым, но остальная часть класса работала в прошлом. Поэтому мы изо всех сил пытаемся понять, что изменилось. Мы также уже пытались заменить аннотацию на Spring Cacheable, но все равно ничего:/ Возможно, это зависит от кода, вызывающего этот новый метод, который относится к другому компоненту Spring, отличному от того, который мы использовали для других методов. Но я все еще не могу найти проблему.

Также попытался вернуть логическое значение вместо логического после ответа ниже, и это не сработало. У нас есть новая зацепка, которая, вероятно, связана с тем, как мы внедряем бин (используя @Autowire). Обновлю, если это действительно так.


person Avi    schedule 10.04.2013    source источник
comment
Каким поставщиком постоянства вы пользуетесь? При использовании гибернации см. HH-5303.   -  person Sven Plath    schedule 10.04.2013
comment
Ну, мы действительно используем Hibernate. Но мы уже использовали @Cacheable в этом проекте, и это сработало. Кэш кэшируется в памяти, а не в БД. Также обратите внимание, что это не аннотация JPA, поэтому я не уверен, что это так. Как вы думаете?   -  person Avi    schedule 10.04.2013
comment
Вы правы, я не читал фактический оператор импорта и предположил, что это была аннотация JPA, о которой вы говорили. Какой сервер приложений вы используете?   -  person Sven Plath    schedule 10.04.2013
comment
Хм, я не знаю этот сервер. Вы включили кэширование в файле persistence.xml? ‹имя свойства=hibernate.cache.use_second_level_cache значение=true /›. Я не знаю, нужно ли это для вашего сервера.   -  person Sven Plath    schedule 10.04.2013
comment
tc-server — это весенняя версия tomcat7, они в основном идентичны. Нужно ли включать это свойство гибернации, даже если я не использую БД в качестве кеша?   -  person Avi    schedule 10.04.2013
comment
Хм. Вы правы, то, что я сказал, не имеет смысла. Может быть, кэширование не работает с логическими типами возврата? Во всех примерах, которые я видел, используются объекты, а не примитивы.   -  person Sven Plath    schedule 10.04.2013
comment
Звучит очень маловероятно. Методы, возвращающие примитивные типы, также могут занимать очень много времени/ресурсов.   -  person Avi    schedule 10.04.2013
comment
Есть еще идеи у кого-нибудь?   -  person Avi    schedule 11.04.2013
comment
Я думаю, что это как сказал @SvenPlath (не читал эти комментарии). Spring ehcache требует, чтобы ваш объект параметров/возврата имел методы equals() и hashCode(), а в примитивах отсутствуют оба метода. Рассмотрите возможность использования классов-оболочек и посмотрите, работает ли это.   -  person g00glen00b    schedule 12.04.2013


Ответы (4)


Эта проблема может быть связана с порядком, в котором Springs загружает bean-компоненты. Попробуйте удалить аннотацию @Autowire из объявления Authenticator и выполните автопроводку вручную. Что-то типа:

/**
 * Class that uses Authenticator
 */

 public class X {

    // Don't use @autowire here
    public Authenticator athenticator;

    public void doSomething() {
         manuallyAutowire();
    }

    public void manuallyAutowire() {
         if(authenticator == null) {
    authenticator = ApplicationContextUtils.getApplicationContext().
                            getBean(authenticator.class);
    }
}

Где

@Component
public class ApplicationContextUtils implements ApplicationContextAware {

    private static ApplicationContext ctx;

    @Override
    public void setApplicationContext(final ApplicationContext appContext) 
                                          throws BeansException {
         ctx = appContext;

    }

    public static ApplicationContext getApplicationContext() {
        return ctx;
    }
}
person Hanan Aharonof    schedule 18.04.2013
comment
Может кто-нибудь уточнить, ПОЧЕМУ это так? Если аннотации просто не работают, это очень плохо. - person Jay; 08.04.2020

Значение параметра cacheName в @Cacheable должно совпадать со значением атрибута name объявления ‹cache› в вашем приложении. контекст

person cRx    schedule 10.04.2013
comment
Вы правы, и это то же самое. Я просто по ошибке скопировал другую запись xml. Я починил это. Спасибо за Ваш ответ! - person Avi; 10.04.2013

Я думаю, что вы смешиваете вещи здесь - вы использовали com.googlecode.ehcache.annotations.Cacheable, если вам нужна поддержка кэширования Springs, на самом деле это должно быть org.springframework.cache.annotation.Cacheable. Тогда кеширующие перехватчики должны работать чисто.

person Biju Kunjummen    schedule 10.04.2013
comment
Проблема в том, что это устаревший код, который отлично работал с кодом и определениями, которые я предоставил. Метод, о котором я говорю здесь, является новым, но остальная часть класса работала в прошлом. Поэтому мы изо всех сил пытаемся понять, что изменилось. Мы также пытались уже заменить аннотацию на Spring Cacheable, но все равно ничего :/ - person Avi; 10.04.2013
comment
О, хорошо, я не знаком с поддержкой аннотаций ehcache Spring, но если вы используете @Cacheable(org.spring..) Spring, вам также придется изменить <ehcache:annotation-driven/> на <cache:annotation-driven/>, префикс кеша в пространстве имен http://www.springframework.org/schema/cache, это должно создать прокси для вас. - person Biju Kunjummen; 10.04.2013

Насколько я знаю, аннотации Spring Ehcache рекомендуют, чтобы оба параметра в качестве возвращаемого объекта имели методы equals() и hashCode(), которых нет у примитивных типов.

Я не уверен, что этот фреймворк преобразует примитивы в их вариант-оболочку (например, Integer или Boolean). Попробуйте вернуть вариант оболочки Boolean вместо примитивного типа и посмотрите, работает ли он.

Еще одна вещь, в которой я не уверен, это то, как (и если) он обрабатывает final параметров. Если моя первая идея не сработает, попробуйте удалить ключевое слово final, если это возможно, и посмотрите, сработает ли оно.

person g00glen00b    schedule 12.04.2013
comment
Хорошо, это отличные материалы! Я проверю и сообщу о результатах. Спасибо! - person Avi; 12.04.2013