【问题标题】:Why doesn't AspectJ compile-time weaving of Spring's @Configurable work?为什么 AspectJ 不编译 Spring 的 @Configurable 工作?
【发布时间】:2010-10-28 10:45:31
【问题描述】:

更新 5: 我已经下载了基于最新 Eclipse 的最新 Spring ToolsSuite IDE。当我将我的项目作为 Maven 项目导入时,Eclipse/STS 似乎使用 Maven 目标来构建我的项目。这意味着 AspectJ 终于在 Eclipse 中正常工作了。

更新 4:我最终只使用 Maven + AspectJ 插件进行编译时编织,有效地绕过了 Eclipse 的机制。

更新 3: 似乎 AspectJ 的 Eclipse 插件破坏了 Eclipse 正确发布到 Tomcat 的能力。只有通过删除项目中的 AspectJ 功能,我才能让它再次正确发布。很烦人。

更新 2:我现在在 Eclipse 中工作。这么说让我很不舒服,但我不知道我是如何从 Eclipse 或 Maven 构建中得到它的。这似乎是一个编译问题而不是运行时问题。

更新 1: 看来我已经通过 Maven 构建让它工作了,但我不知道如何。 Eclipse 仍然无法正常工作。我在 pom.xml 中唯一更改的是添加这些(无关紧要的?)配置参数:

<source>1.6</source>
<complianceLevel>1.6</complianceLevel>
<verbose>true</verbose>
<showWeaveInfo>true</showWeaveInfo>
<outxml>true</outxml>

我真的很担心我重复了this problem,所有的工作都不一致。随着我了解更多信息,我会不断更新这个问题。

关于 Eclipse,我取得了一些进展,将我希望编织的二进制方面(在本例中为 spring-aspects.jar)复制到我的类路径中。然后我将这个现在的外部 jar 添加到我的 Aspect Path 中。完成此操作后,Eclipse 会在我的代码中正确显示 AspectJ 标记。令人讨厌的是,我不能将 spring-aspects.jar 留在我的 Java Build Path 中,该路径由 Maven 通过 Maven 插件为我维护。然而,出于某种原因,AspectJ 插件看不到二进制方面,除非它们被显式添加到 Aspect Path


原帖: @Configurable 是一个 Spring 注解,它允许将依赖项注入到 Spring 外部实例化的对象中(例如,通过 Hibernate 或某些 Factory 类)。

我之前在加载时编织中使用了这个注释,它大部分都有效。有时我会启动并且不会注入任何东西。这个问题催生了this StackOverflow question。答案不多,但大多数人建议我尝试编译时编织,因为可靠性更高。

我为 Eclipse 和 Maven 安装了 AspectJ 插件。这两者都产生似乎是正确编译的类。在 AspectJ 编译之前,我在文本编辑器中打开了其中一个类,但没有发现对 AspectJ 的引用。我在 AspectJ 编译后打开它,Eclipse 和 Maven 生成的版本都引用了 org.aspectj.weaver.MethodDeclarationLineNumber。这就是为什么我认为它被正确编译的原因。问题是一旦部署,就不会注入任何依赖项。

我的 Spring applicationContext.xml 确实包含以下内容:

    <context:spring-configured />

    <context:component-scan base-package="com.myapp" />

以上是标记为@Configurable 的类完成DI 所需要的吗?在从加载时编织到编译时编织的转换过程中,我从我的applicationContext.xml,以及来自我的 context.xml 的 Spring 的 Tomcat 编织器。

如何进一步调查此问题?可能的原因是什么?

【问题讨论】:

    标签: java maven aop spring-aop compile-time-weaving


    【解决方案1】:

    如果你没有为这个注解正确配置你的spring,那么创建一个@configurable 类Autowired 的字段会抛出NullPointerException。 按照以下步骤使@configurable 注释正常工作

    此方法称为 AspectJ 构建时编织,用于将 spring bean 注入到非 spring-made 类中

    第一步是在eclipse中安装这些插件:

    从这两个更新站点安装 eclipse 建议的任何内容:

    http://download.eclipse.org/tools/ajdt/43/update
    http://dist.springsource.org/release/AJDT/configurator/ 
    

    安装后,右键单击项目并执行:

    Configure > Convert to Aspectj
    Maven > Update
    

    接下来,您需要将这些添加到您的 pom.xml:

    在依赖项下添加:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>4.0.2.RELEASE</version>
    </dependency>
    

    在插件下添加:

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.5</version>
                <configuration>
                    <showWeaveInfo>true</showWeaveInfo>
                    <source>1.7</source>
                    <target>1.7</target>
                    <Xlint>ignore</Xlint>
                    <complianceLevel>1.7</complianceLevel>
                    <encoding>UTF-8</encoding>
                    <verbose>false</verbose>
                    <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>
                <dependencies>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjrt</artifactId>
                        <version>1.7.0</version>
                    </dependency>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjtools</artifactId>
                        <version>1.7.0</version>
                    </dependency>
                </dependencies>
            </plugin>
    

    重要提示:不要在&lt;build&gt; 标签下使用任何&lt;pluginManagment&gt; 标签。 你的 pom.xml 需要是这样的:

    <project ....>
        ....
        <dependencies>
            <dependency> 
                        ....
            </dependency>
                    ....
        </dependencies>
        <build>
            <plugins>
                <plugin>
                                ....
                </plugin>
                            ....
            </plugins>
        </build>
    </project>
    

    最后将 &lt;context:spring-configured /&gt; 添加到您的 Spring 应用程序上下文配置文件中。

    现在您可以将 POJO 类注释为 @Configurable 并使用 @Autowired 注释在其中注入 spring bean。这样,每当您创建该 POJO 的新实例时,它将自动配置(例如注入依赖项)。

    【讨论】:

      【解决方案2】:

      我已在我的应用程序中成功配置了加载时编织,如果您可以选择这样做的话。

      我的环境:

      • JDK-1.6
      • Spring-2.5.6
      • 带有 eclipselink-1.1.0 的 JPA

      配置详情:

      Spring XML 配置:

      <context:annotation-config/>
      <context:spring-configured/>
      <context:load-time-weaver/>
      
      <bean id="baseEntity" class="package.name.BaseEntity" scope="prototype">
        <property name="historyHandler" ref="historyHandler" />
      </bean>
      
      <bean id="historyHandler" class="package.name.HistoryJpaHandler" scope="prototype">
        <property name="historyDao" ref="historyDao" />
      </bean>
      
      <bean id="historyDao" class="package.name.HistoryJpaDao">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
      </bean>
      

      弹簧注解

      @Configurable("baseEntity")
      public abstract class BaseEntity
      
      @Configurable("historyHandler")
      public class HistoryJpaHandler extends SessionEventAdapter implements HistoryHandler 
      

      Java 虚拟机参数

      <JAVA_HOME>/bin/java -javaagent:/full/path/to/spring-agent-2.5.6.jar
      

      historyHandler 和 baseEntitty 的实例是由 ecriselink 创建的。 baseEntitty 中的 historyHandler 和 historyHandler 中的 historyDao 由 load-timeweaving 设置。

      您可以在 Eclipse 运行配置或 Tomcats catalina.sh/bat 中设置 VM 参数。

      【讨论】:

        【解决方案3】:

        它适用于我们在 maven 上使用编译时编织,尝试添加以下插件:

        <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
            <compilerVersion>1.6</compilerVersion>
            <fork>true</fork>
            <source>1.6</source>
            <target>1.6</target>
        </configuration>
        </plugin>
        
        <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>aspectj-maven-plugin</artifactId>
        <executions>
            <execution>
                <id>compile</id>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <verbose>false</verbose>
                    <outxml>true</outxml>
                    <aspectLibraries>
                        <aspectLibrary>
                            <groupId>org.springframework</groupId>
                            <artifactId>spring-aspects</artifactId>
                        </aspectLibrary>
                    </aspectLibraries>
                </configuration>
                <goals>
                    <goal>compile</goal>
                </goals>
            </execution>
            <execution>
                <id>test-compile</id>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <verbose>false</verbose>
                    <aspectLibraries>
                        <aspectLibrary>
                            <groupId>org.springframework</groupId>
                            <artifactId>spring-aspects</artifactId>
                        </aspectLibrary>
                    </aspectLibraries>
                </configuration>
                <goals>
                    <goal>test-compile</goal>
                </goals>
            </execution>
        </executions>
        <dependencies>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.6.4</version>
            </dependency>
        </dependencies>
        </plugin>
        

        它作为两个单独的执行步骤完成,允许您添加不同的方面库以进行单元测试和编译。

        您还需要为 spring-aspects 库添加以下依赖项:

            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
                <scope>compile</scope>
            </dependency>
        

        【讨论】:

        • 您需要将 1.6 添加到 aspectj-maven-plugin 配置,否则根据错误消息它以错误 (configure.incompatibleComplianceForSource) 结束,可能是因为 complianceLevel 默认为 1.4 和它与您的情况下为 1.6 的源设置不同
        • 应用此建议后,我遇到的问题是我的测试不起作用,因为调用了 aspectj 方面并且内部方面存在未初始化的字段,因此我看到了 NPE
        【解决方案4】:

        就您的 Eclipse 类路径问题而言,您可能会发现这很有用。

        m2eclipse plugin 有一个可选的AJDT integration。集成读取 aspectj-maven-plugin 配置的 aspectLibraries 部分,并将 jars 贡献给 Eclipse 的 Aspect Path。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-02-15
          • 1970-01-01
          • 2015-08-17
          • 2013-03-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多