Java 为什么 Spring 的 @Configurable 的 AspectJ 编译时编织不起作用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/901632/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why doesn't AspectJ compile-time weaving of Spring's @Configurable work?
提问by Robert Campbell
Update 5:I've downloaded the latest Spring ToolsSuite IDE based on the latest Eclipse. When I import my project as a Maven project, Eclipse/STS appears to use the Maven goals for building my project. This means AspectJ finally works correctly in Eclipse.
更新 5:我已经下载了基于最新 Eclipse 的最新 Spring ToolsSuite IDE。当我将我的项目作为 Maven 项目导入时,Eclipse/STS 似乎使用 Maven 目标来构建我的项目。这意味着 AspectJ 最终可以在 Eclipse 中正常工作。
Update 4:I have ended up just using Maven + AspectJ plugin for compile-time weaving, effectively bypassing Eclipse's mechanism.
更新 4:我最终只使用 Maven + AspectJ 插件进行编译时编织,有效地绕过了 Eclipse 的机制。
Update 3:It seems AspectJ's Eclipse plug-in breaks Eclipse's ability to correctly Publish to Tomcat. Only by removing the AspectJ capability on a project can I get it to properly Publish again. Very annoying.
更新 3:似乎 AspectJ 的 Eclipse 插件破坏了 Eclipse 正确发布到 Tomcat 的能力。只有删除项目上的 AspectJ 功能,我才能让它再次正确发布。很烦人。
Update 2:I have this now working in Eclipse. It makes me very uncomfortable to say this, but I have no idea how I got it working from either Eclipse or Maven builds. It appears to be a compile issue rather than a run-time issue.
更新 2:我现在在 Eclipse 中使用它。这么说让我很不舒服,但我不知道我是如何从 Eclipse 或 Maven 构建中得到它的。它似乎是一个编译问题而不是运行时问题。
Update 1:It appears I've gotten this to work via Maven builds, but I have no idea how. Eclipse still doesn't work. The only thing I changed in the pom.xmlwas adding these (insignificant?) configuration parameters:
更新 1:看来我已经通过 Maven 构建让它工作了,但我不知道如何。Eclipse 仍然不起作用。我在pom.xml 中唯一改变的是添加这些(无关紧要的?)配置参数:
<source>1.6</source>
<complianceLevel>1.6</complianceLevel>
<verbose>true</verbose>
<showWeaveInfo>true</showWeaveInfo>
<outxml>true</outxml>
I'm actually worried that I have a repeat of this problem, where everything works inconsistently. I will keep this question updated as I learn more.
我实际上很担心我会重复这个问题,其中一切都不一致。随着我了解更多,我会不断更新这个问题。
With regards to Eclipse, I made some progress by taking the binary aspects I wish to weave - in this case spring-aspects.jar- and copying it out of my classpath. I then add this now external jar to my Aspect Path. After doing this, Eclipse properly shows me AspectJ markers in my code. It's annoying that I can't just leave spring-aspects.jarin my Java Build Pathwhich is maintained by Maven for me via the Maven plug-in. For some reason, however, the AspectJ plug-in doesn't see the binary aspects unless they're explicitly added to the Aspect Path.
关于 Eclipse,我通过采用我希望编织的二进制方面取得了一些进展 - 在本例中为spring-aspects.jar- 并将其从我的类路径中复制出来。然后我将这个外部 jar 添加到我的Aspect Path。这样做之后,Eclipse 在我的代码中正确地显示了 AspectJ 标记。令人讨厌的是,我不能将spring-aspects.jar留在我的Java Build Path 中,该路径由 Maven 通过 Maven 插件为我维护。然而,出于某种原因,AspectJ 插件不会看到二进制方面,除非它们被明确添加到Aspect Path 中。
Original Post:@Configurable is a Spring annotation that allows dependencies to be injected into objects instantiated external to Spring (for example, by Hibernate or some Factory class).
原帖:@Configurable 是一个 Spring 注释,它允许将依赖项注入到 Spring 外部实例化的对象中(例如,通过 Hibernate 或某些 Factory 类)。
I was using this annotation previously with load-time weaving and it mostlyworked. Occasionally I would boot up and nothing would get injected. This issue spawned this StackOverflow question. There weren't many answers, but most suggested that I try compile-time weaving instead due to greater reliability.
我之前在加载时编织中使用了这个注释,并且它大部分都有效。有时我会启动,但不会注入任何内容。这个问题产生了这个 StackOverflow 问题。没有多少答案,但大多数人建议我尝试编译时编织,因为可靠性更高。
I installed the AspectJ plug-in for Eclipse and Maven. Both of these produce what appears to be properly compiled classes. I've opened up one of the classes in a text editor before AspectJ compilation and found no references to AspectJ. I opened it up after AspectJ compilation and both Eclipse and Maven generated versions have a reference to org.aspectj.weaver.MethodDeclarationLineNumber. This is why I assume it's being properly compiled. The problem is that once deployed, no dependencies get injected.
我为 Eclipse 和 Maven 安装了 AspectJ 插件。这两者都产生了似乎是正确编译的类。在 AspectJ 编译之前,我在文本编辑器中打开了其中一个类,但没有发现对 AspectJ 的引用。我在 AspectJ 编译后打开它,Eclipse 和 Maven 生成的版本都有对org.aspectj.weaver.MethodDeclarationLineNumber的引用。这就是为什么我认为它被正确编译的原因。问题是一旦部署,就不会注入任何依赖项。
My Spring applicationContext.xmldoes include the following:
我的 Spring applicationContext.xml确实包括以下内容:
<context:spring-configured />
<context:component-scan base-package="com.myapp" />
Is the above all that's needed for classes marked @Configurable to have DI done? During the conversion from load-time weaving to compile-time weaving, I removed META-INF/aop.xml, <context:load-time-weaver />from my applicationContext.xml, and Spring's Tomcat weaver from my context.xml.
以上是标记为@Configurable 的类完成 DI 所需的全部内容吗?在从加载时编织到编译时编织的转换过程中,我从applicationContext.xml 中删除了META-INF/aop.xml、<context:load-time-weaver />,并从我的context.xml 中删除了Spring 的 Tomcat weaver 。
How can I investigate this problem further? What are possible causes?
我怎样才能进一步调查这个问题?可能的原因是什么?
采纳答案by Stephen Houston
It works for us on maven using compile time weaving, try adding the following plugins:
它使用编译时编织在 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>
Its done as two separate execution steps to allow you to add different aspect libraries for unit testing and compilation.
它作为两个单独的执行步骤完成,允许您为单元测试和编译添加不同的方面库。
You'll also need the following dependency added for the spring-aspects library:
您还需要为 spring-aspects 库添加以下依赖项:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<scope>compile</scope>
</dependency>
回答by u?6??n? ???u?p
I successfully configured load-time weaving in my app, if this is an alternative for you.
我在我的应用程序中成功配置了加载时编织,如果这对你来说是一个替代方案。
My environment:
我的环境:
- JDK-1.6
- Spring-2.5.6
- JPA with eclipselink-1.1.0
- JDK-1.6
- Spring-2.5.6
- 带有 eclipselink-1.1.0 的 JPA
Configuration details:
配置详情:
Spring XML configuration:
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>
Spring annotations
Spring注解
@Configurable("baseEntity")
public abstract class BaseEntity
@Configurable("historyHandler")
public class HistoryJpaHandler extends SessionEventAdapter implements HistoryHandler
Java VM Parameter
Java 虚拟机参数
<JAVA_HOME>/bin/java -javaagent:/full/path/to/spring-agent-2.5.6.jar
Instances of historyHandler and baseEntitty are created by ecliselink. historyHandler in baseEntitty and historyDao in historyHandler is set by load-timeweaving.
historyHandler 和 baseEntitty 的实例由 ecliselink 创建。baseEntitty 中的 historyHandler 和 historyHandler 中的 historyDao 由 load-timeweaving 设置。
You can set the VM Parameter in Eclipse run configuration or in Tomcats catalina.sh/bat.
您可以在 Eclipse 运行配置或 Tomcats catalina.sh/bat 中设置 VM 参数。
回答by Rich Seller
As far as your Eclipse classpath issues are concerned, you might find this useful.
就您的 Eclipse 类路径问题而言,您可能会发现这很有用。
The m2eclipse pluginhas an optional AJDT integration. The integration reads the aspectLibraries section of the aspectj-maven-plugin's configuration, and contributes the jars to Eclipse's Aspect Path.
该m2eclipse插件有一个可选的AJDT整合。集成读取 aspectj-maven-plugin 配置的 aspectLibraries 部分,并将 jars 提供给 Eclipse 的 Aspect Path。
回答by Meysam Feghhi
making a field of a @configurable class Autowired throws NullPointerException if you do not configure your spring properly for this annotation. follow these steps to make @configurable annotations work properly
如果你没有为这个注解正确配置你的弹簧,那么创建一个 @configurable 类 Autowired 的字段会抛出 NullPointerException 。按照以下步骤使@configurable 注释正常工作
This method is called AspectJ build time weaving to inject spring beans to your non-spring-made classes.
此方法称为AspectJ 构建时编织,以将 spring bean 注入您的非 spring 制造类。
First step is to install these plugins in eclipse:
第一步是在eclipse中安装这些插件:
From these two update sites install whatever eclipse suggests:
从这两个更新站点安装 eclipse 建议的任何内容:
http://download.eclipse.org/tools/ajdt/43/update
http://dist.springsource.org/release/AJDT/configurator/
After installing,right-click on project and Do:
安装后,右键单击项目并执行:
Configure > Convert to Aspectj
Maven > Update
Next, you need to add these to your pom.xml:
接下来,您需要将这些添加到您的 pom.xml 中:
Under Dependencies Add:
在依赖项下添加:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.0.2.RELEASE</version>
</dependency>
Under Plugins Add:
在插件下添加:
<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>
Important:DO NOT use any <pluginManagment>
tag under <build>
tag.
your pom.xml needs to be something like this:
重要提示:不要<pluginManagment>
在<build>
标签下使用任何标签。你的 pom.xml 需要是这样的:
<project ....>
....
<dependencies>
<dependency>
....
</dependency>
....
</dependencies>
<build>
<plugins>
<plugin>
....
</plugin>
....
</plugins>
</build>
</project>
finally add <context:spring-configured />
to your spring application context config file.
最后添加<context:spring-configured />
到您的 spring 应用程序上下文配置文件中。
Now you can annotate a POJO class as @Configurable
and inject spring beans in it using @Autowired
annotation. this way whenever you make a new instance of that POJO it will be configured (e.g. injected with dependencies) automatically.
现在您可以将 POJO 类注释为 as@Configurable
并使用@Autowired
注释在其中注入 spring bean 。这样,每当您创建该 POJO 的新实例时,它将自动配置(例如注入依赖项)。