【问题标题】:Spring: Do I need @EnableAspectJAutoProxy with Compile time weaving?Spring:我需要 @EnableAspectJAutoProxy 和编译时间编织吗?
【发布时间】:2014-03-01 15:09:53
【问题描述】:

我浏览了互联网并找到了一些建议,也尝试了不同的配置,但我完全不确定它是否能正常工作。

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>

因为之前似乎我总是必须在 Eclipse 中执行 Project -&gt; Clean,然后是 Tomcat -&gt; 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 -&gt; CleanTomcat -&gt; Clean。 (否则它只是忽略了@Cacheable 注释并简单地调用了方法)

谢谢!

【问题讨论】:

    标签: eclipse spring maven caching aspectj


    【解决方案1】:

    首先,您当前的设置将永远无法与@EnableAspectJAutoProxy 一起使用。 Spring AOP 使用代理来应用方面。您的 @Scheduled 在内部调用该方法,因此永远不会通过代理,您将永远不会有缓存。

    接下来您使用编译时编织,因此您不应该使用@EnableAspectJAutoProxy,因为这些方面已经编织进去。如果这不起作用,您的 pom 和 Eclipse 的设置就会出现问题。

    试图让 Eclipse 和 Maven 一起工作是(或可能是)一项艰巨的任务。关于 AspectJ 和 Maven,请参阅 aspectj-maven-plugin not covered by lifecycle in Keplerthis blog 也可能会有所帮助。

    【讨论】:

    • 感谢您的建议。 1. 所以如果我理解正确的话,我应该删除@EnableAspectJAutoProxy,因为我想使用编译时编织。 Eclipse 和 Maven 正在为其他所有事情一起工作(即生成用于查询数据库的类文件)。 2. 确实将@Scheduled 方法放在那里是为了在内部调用@Cacheable 方法,因为这是一个只能使用AspectJ 的场景。使用标准 AOP 代理时,永远不应调用 AnnotationCacheAspect。所以我认为带有@Cacheable 的AspectJ 可以以某种方式工作?!
    • 如果您使用编译(或加载时间)编织,它将起作用,而不是使用默认代理方法。也许我应该换个说法,但是让 eclipse 与你所有的 maven 插件一起工作可能会很痛苦。 (这就是我切换到 IntelliJ 的原因之一,它对 Maven 的支持比 Eclipse 更好)。
    • 现在我很困惑:-D ...所以这就是我想要的:简单的编译时编织。我需要@EnableAspectJAutoProxy 吗?也许您可以详细说明@EnableAspectJAutoProxy 的作用? JavaDoc 说 Enables support for handling components marked with AspectJ's @Aspect annotation, similar to functionality found in Spring's &lt;aop:aspectj-autoproxy&gt; XML element 在我听来就像 它启用了 AspectJ
    • 编辑:我刚刚从 AppConfig.java 中删除了 @EnableAspectJAutoProxy 注释,它仍然有效 :) 但我仍然不明白它有什么好处。
    • @EnableAspectJAutoProxy,顾名思义,就是用来在代理模式下启用Spring AOP。它将创建代理来应用 AOP(参见 Spring 参考指南对此进行了解释)。
    猜你喜欢
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-21
    • 1970-01-01
    • 2011-03-09
    • 2016-12-16
    相关资源
    最近更新 更多