Весна: Нужно ли @EnableAspectJAutoProxy с переплетением времени компиляции?

Я просмотрел Интернет и нашел несколько предложений, а также попробовал различные конфигурации, но я совершенно не уверен, работает ли он правильно.

pom.xml (полный pom.xml: http://pastebin.com/5Y2qksTH):

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.eclipse.m2e</groupId>
                <artifactId>lifecycle-mapping</artifactId>
                <version>1.0.0</version>
                <configuration>
                    <lifecycleMappingMetadata>
                        <pluginExecutions>
                            <pluginExecution>
                                <pluginExecutionFilter>
                                    <groupId>org.codehaus.mojo</groupId>
                                    <artifactId>aspectj-maven-plugin</artifactId>
                                    <versionRange>[1.0,)</versionRange>
                                    <goals>
                                        <goal>test-compile</goal>
                                        <goal>compile</goal>
                                    </goals>
                                </pluginExecutionFilter>
                                <action>
                                    <execute>
                                        <runOnConfiguration>true</runOnConfiguration>
                                        <runOnIncremental>true</runOnIncremental>
                                    </execute>
                                </action>
                            </pluginExecution>
                        </pluginExecutions>
                    </lifecycleMappingMetadata>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>

    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.5</version>
            <configuration>
                <Xlint>warning</Xlint>
                <complianceLevel>1.7</complianceLevel>
                <source>1.7</source>
                <target>1.7</target>
                <encoding>UTF-8</encoding>
                <aspectLibraries>
                    <aspectLibrary>
                        <groupId>org.springframework</groupId>
                        <artifactId>spring-aspects</artifactId>
                    </aspectLibrary>
                </aspectLibraries>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <goal>test-compile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

я добавил

<execute>
    <runOnConfiguration>true</runOnConfiguration>
    <runOnIncremental>true</runOnIncremental>
</execute>

потому что раньше казалось, что мне всегда приходилось делать Project -> Clean в затмении и после Tomcat -> Clean, Иначе он всегда выполнял мой кэшированный метод. Теперь, похоже, работает автоматически.

CacheableConfig.java:

@EnableCaching(mode = AdviceMode.ASPECTJ)
public class CacheableConfig implements CachingConfigurer {
    @Override
    public CacheManager cacheManager() {
        return new ConcurrentMapCacheManager("testCache");
    }

    @Override
    public KeyGenerator keyGenerator() {
        return new SimpleKeyGenerator();
    }
}

AppConfig.java:

@EnableAspectJAutoProxy
public class AppConfig {}

Без @EnableAspectJAutoProxy это не сработало вообще.

MyTestServiceImpl.java:

@Service
public class MyTestServiceImpl implements MyTestService {
    @Scheduled(initialDelay=10000, fixedDelay=30000)
    public void a() {
        long time = System.currentTimeMillis();
        System.out.println("START");
        System.out.println("returned: " + b(0));
        System.out.println("returned: " + b(1));
        System.out.println("returned: " + b(0));
        System.out.println("returned: " + b(1));
        System.out.println("returned: " + b(2));
        System.out.println("END: " + (System.currentTimeMillis() - time));
    }

    @Cacheable("testCache")
    public int b(int i) {
        System.out.println("INSIDE CACHED METHOD");
        i++;
        try {
            Thread.sleep(2000);
        } catch(InterruptedException ex) {}
        return i;
    }
}

Примечание: я просто использую @Scheduled для автоматического вызова метода несколько раз.

Выход:

START
2014-03-01 15:53:25,796 DEBUG    o.s.c.annotation.AnnotationCacheOperationSource: 109 - Adding cacheable method 'b' with attribute: [CacheableOperation[public int MyTestServiceImpl.b(int)] caches=[testCache] | key='' | condition='' | unless='']
2014-03-01 15:53:25,797 TRACE            o.s.cache.aspectj.AnnotationCacheAspect: 318 - Computed cache key 0 for operation CacheableOperation[public int MyTestServiceImpl.b(int)] caches=[testCache] | key='' | condition='' | unless=''
INSIDE CACHED METHOD
returned: 1
2014-03-01 15:53:27,798 TRACE            o.s.cache.aspectj.AnnotationCacheAspect: 318 - Computed cache key 1 for operation CacheableOperation[public int MyTestServiceImpl.b(int)] caches=[testCache] | key='' | condition='' | unless=''
INSIDE CACHED METHOD
returned: 2
2014-03-01 15:53:29,799 TRACE            o.s.cache.aspectj.AnnotationCacheAspect: 318 - Computed cache key 0 for operation CacheableOperation[public int MyTestServiceImpl.b(int)] caches=[testCache] | key='' | condition='' | unless=''
2014-03-01 15:53:29,799 TRACE            o.s.cache.aspectj.AnnotationCacheAspect: 318 - Computed cache key 0 for operation CacheableOperation[public int MyTestServiceImpl.b(int)] caches=[testCache] | key='' | condition='' | unless=''
returned: 1
2014-03-01 15:53:29,799 TRACE            o.s.cache.aspectj.AnnotationCacheAspect: 318 - Computed cache key 1 for operation CacheableOperation[public int MyTestServiceImpl.b(int)] caches=[testCache] | key='' | condition='' | unless=''
2014-03-01 15:53:29,799 TRACE            o.s.cache.aspectj.AnnotationCacheAspect: 318 - Computed cache key 1 for operation CacheableOperation[public int MyTestServiceImpl.b(int)] caches=[testCache] | key='' | condition='' | unless=''
returned: 2
2014-03-01 15:53:29,799 TRACE            o.s.cache.aspectj.AnnotationCacheAspect: 318 - Computed cache key 2 for operation CacheableOperation[public int MyTestServiceImpl.b(int)] caches=[testCache] | key='' | condition='' | unless=''
INSIDE CACHED METHOD
returned: 3
END: 6018

START
2014-03-01 15:54:01,801 TRACE            o.s.cache.aspectj.AnnotationCacheAspect: 318 - Computed cache key 0 for operation CacheableOperation[public int MyTestServiceImpl.b(int)] caches=[testCache] | key='' | condition='' | unless=''
2014-03-01 15:54:01,801 TRACE            o.s.cache.aspectj.AnnotationCacheAspect: 318 - Computed cache key 0 for operation CacheableOperation[public int MyTestServiceImpl.b(int)] caches=[testCache] | key='' | condition='' | unless=''
returned: 1
2014-03-01 15:54:01,801 TRACE            o.s.cache.aspectj.AnnotationCacheAspect: 318 - Computed cache key 1 for operation CacheableOperation[public int MyTestServiceImpl.b(int)] caches=[testCache] | key='' | condition='' | unless=''
2014-03-01 15:54:01,801 TRACE            o.s.cache.aspectj.AnnotationCacheAspect: 318 - Computed cache key 1 for operation CacheableOperation[public int MyTestServiceImpl.b(int)] caches=[testCache] | key='' | condition='' | unless=''
returned: 2
2014-03-01 15:54:01,801 TRACE            o.s.cache.aspectj.AnnotationCacheAspect: 318 - Computed cache key 0 for operation CacheableOperation[public int MyTestServiceImpl.b(int)] caches=[testCache] | key='' | condition='' | unless=''
2014-03-01 15:54:01,802 TRACE            o.s.cache.aspectj.AnnotationCacheAspect: 318 - Computed cache key 0 for operation CacheableOperation[public int MyTestServiceImpl.b(int)] caches=[testCache] | key='' | condition='' | unless=''
returned: 1
2014-03-01 15:54:01,802 TRACE            o.s.cache.aspectj.AnnotationCacheAspect: 318 - Computed cache key 1 for operation CacheableOperation[public int MyTestServiceImpl.b(int)] caches=[testCache] | key='' | condition='' | unless=''
2014-03-01 15:54:01,802 TRACE            o.s.cache.aspectj.AnnotationCacheAspect: 318 - Computed cache key 1 for operation CacheableOperation[public int MyTestServiceImpl.b(int)] caches=[testCache] | key='' | condition='' | unless=''
returned: 2
2014-03-01 15:54:01,802 TRACE            o.s.cache.aspectj.AnnotationCacheAspect: 318 - Computed cache key 2 for operation CacheableOperation[public int MyTestServiceImpl.b(int)] caches=[testCache] | key='' | condition='' | unless=''
2014-03-01 15:54:01,802 TRACE            o.s.cache.aspectj.AnnotationCacheAspect: 318 - Computed cache key 2 for operation CacheableOperation[public int MyTestServiceImpl.b(int)] caches=[testCache] | key='' | condition='' | unless=''
returned: 3
END: 1

Это в основном выглядит хорошо:

  • Первый звонок a() занимает 6 секунд, потому что b() вызывается эффективно 3 раза.
  • Второй звонок a() занимает 1 мс, потому что все приходит из кеша.
  • Возвращаемые значения в порядке.

Вопросы:

  1. Почему эти журналы TRACE Computed cache key x for operation ... там всегда два раза? Похоже, метод вычисления вызывается дважды?!

  2. Конфигурация в порядке? Потому что я не совсем уверен, будет ли это всегда работать так, как ожидалось, особенно потому, что мне пришлось использовать Project -> Clean а также Tomcat -> Clean иногда. (иначе он просто проигнорировал @Cacheable аннотации и просто называется метод)

Спасибо!

1 ответ

Решение

Прежде всего, ваши текущие настройки никогда не будут работать с @EnableAspectJAutoProxy, Spring AOP использует прокси для применения аспектов. Ваш @Scheduled вызывает метод внутри себя и поэтому никогда не пройдет через прокси, и у вас никогда не будет кэширования.

Рядом с этим вы используете ткачество времени компиляции, поэтому вы не должны использовать @EnableAspectJAutoProxy поскольку аспекты уже сплетены. Если это не работает, у вас есть проблема в настройке вашего pom вместе с Eclipse.

Попытка заставить Eclipse и Maven работать вместе является (или может быть) сложной задачей. Что касается AspectJ и Maven, см. Aspectj-maven-plugin, не охваченный жизненным циклом в Kepler, и этот блог также может быть полезен.

Другие вопросы по тегам