如何使用AspectJ编织Hibernate?

huangapple go评论91阅读模式
英文:

How to weave hibernate by aspectj?

问题

我有一个带有切面的库,它扫描所有语句执行并对SQL语句执行一些逻辑。

@Pointcut("target(java.sql.Statement)")
public void statement() {}

@AfterReturning("!within(AnalyzerAspect) && statement() && args(sql)")
public void after(JoinPoint jp, String sql) throws Throwable {
  // 一些逻辑
}

当我在JDBC操作中使用它时,它正常工作。我还将它与Spring JDBC一起使用,如下所示:

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>aspectj-maven-plugin</artifactId>
  <version>${aspect.compiler.plugin.version}</version>
  <configuration>
    <weaveDependencies>
      <weaveDependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
      </weaveDependency>
    </weaveDependencies>
    <aspectLibraries>
      <aspectLibrary>
        <groupId>edu.ifmo.diploma</groupId> <!-- 我的库 -->
        <artifactId>db-analyzer</artifactId>
      </aspectLibrary>
    </aspectLibraries>
    <complianceLevel>11</complianceLevel>
    <showWeaveInfo>true</showWeaveInfo>
    <Xlint>ignore</Xlint>
    <encoding>UTF-8</encoding>
  </configuration>
  <executions>
    <execution>
      <goals>
        <goal>compile</goal>
        <goal>test-compile</goal>
      </goals>
    </execution>
  </executions>
</plugin>

但是,当我尝试以相同的方式编织Hibernate核心依赖项时,

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>aspectj-maven-plugin</artifactId>
  <version>${aspect.compiler.plugin.version}</version>
  <configuration>
    <weaveDependencies>
      <weaveDependency>
        <groupId>org.hibernate.orm</groupId>
        <artifactId>hibernate-core</artifactId>
      </weaveDependency>
    </weaveDependencies>
    <aspectLibraries>
      <aspectLibrary>
        <groupId>edu.ifmo.diploma</groupId> <!-- 我的库 -->
        <artifactId>db-analyzer</artifactId>
      </aspectLibrary>
    </aspectLibraries>
    <complianceLevel>11</complianceLevel>
    <showWeaveInfo>true</showWeaveInfo>
    <Xlint>ignore</Xlint>
    <encoding>UTF-8</encoding>
  </configuration>
  <executions>
    <execution>
      <goals>
        <goal>compile</goal>
        <goal>test-compile</goal>
      </goals>
    </execution>
  </executions>
</plugin>

我在aspectj编译任务中遇到错误。

在日志中,我发现了许多类似以下的NPE(264个):

end public class org.hibernate.metamodel.mapping.ordering.ast.ParseTreeVisitor
 -- (NullPointerException) Cannot invoke "org.aspectj.weaver.ResolvedMember.getGenericParameterTypes()" because the return value of "org.aspectj.weaver.Shadow.getResolvedSignature()" is null
Cannot invoke "org.aspectj.weaver.ResolvedMember.getGenericParameterTypes()" because the return value of "org.aspectj.weaver.Shadow.getResolvedSignature()" is null
java.lang.NullPointerException: Cannot invoke "org.aspectj.weaver.ResolvedMember.getGenericParameterTypes()" because the return value of "org.aspectj.weaver.Shadow.getResolvedSignature()" is null

如何解决这个问题?也许aspectj插件有一个选项,可以跳过一些编织如果它们引起错误,或者也许我需要添加一些属性来解决通用参数类型?

完整的aspectj编译日志

我没有找到与编织中相同问题的链接,但有一个与最接近的异常相关的链接:链接

英文:

I have a library with aspect which scan all statement executions and doing some logic with sql sentence.

@Pointcut(&quot;target(java.sql.Statement)&quot;)
public void statement() {}

@AfterReturning(&quot;!within(AnalyzerAspect) &amp;&amp; statement() &amp;&amp; args(sql)&quot;)
public void after(JoinPoint jp, String sql) throws Throwable {
  // some logic
}

When I use it for jdbc operations it works fine. I also used it with spring-jdbc like that

&lt;plugin&gt;
  &lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;
  &lt;artifactId&gt;aspectj-maven-plugin&lt;/artifactId&gt;
  &lt;version&gt;${aspect.compiler.plugin.version}&lt;/version&gt;
  &lt;configuration&gt;
    &lt;weaveDependencies&gt;
      &lt;weaveDependency&gt;
        &lt;groupId&gt;org.springframework&lt;/groupId&gt;
        &lt;artifactId&gt;spring-jdbc&lt;/artifactId&gt;
      &lt;/weaveDependency&gt;
    &lt;/weaveDependencies&gt;
    &lt;aspectLibraries&gt;
      &lt;aspectLibrary&gt;
        &lt;groupId&gt;edu.ifmo.diploma&lt;/groupId&gt; &lt;!-- My library --&gt;
        &lt;artifactId&gt;db-analyzer&lt;/artifactId&gt;
      &lt;/aspectLibrary&gt;
    &lt;/aspectLibraries&gt;
    &lt;complianceLevel&gt;11&lt;/complianceLevel&gt;
    &lt;showWeaveInfo&gt;true&lt;/showWeaveInfo&gt;
    &lt;Xlint&gt;ignore&lt;/Xlint&gt;
    &lt;encoding&gt;UTF-8&lt;/encoding&gt;
  &lt;/configuration&gt;
  &lt;executions&gt;
    &lt;execution&gt;
      &lt;goals&gt;
        &lt;goal&gt;compile&lt;/goal&gt;
        &lt;goal&gt;test-compile&lt;/goal&gt;
      &lt;/goals&gt;
    &lt;/execution&gt;
  &lt;/executions&gt;
&lt;/plugin&gt;

But when I try to weave hibernate core dependency the same way

&lt;plugin&gt;
  &lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;
  &lt;artifactId&gt;aspectj-maven-plugin&lt;/artifactId&gt;
  &lt;version&gt;${aspect.compiler.plugin.version}&lt;/version&gt;
  &lt;configuration&gt;
    &lt;weaveDependencies&gt;
      &lt;weaveDependency&gt;
        &lt;groupId&gt;org.hibernate.orm&lt;/groupId&gt;
        &lt;artifactId&gt;hibernate-core&lt;/artifactId&gt;
      &lt;/weaveDependency&gt;
    &lt;/weaveDependencies&gt;
    &lt;aspectLibraries&gt;
      &lt;aspectLibrary&gt;
        &lt;groupId&gt;edu.ifmo.diploma&lt;/groupId&gt; &lt;!-- My library --&gt;
        &lt;artifactId&gt;db-analyzer&lt;/artifactId&gt;
      &lt;/aspectLibrary&gt;
    &lt;/aspectLibraries&gt;
    &lt;complianceLevel&gt;11&lt;/complianceLevel&gt;
    &lt;showWeaveInfo&gt;true&lt;/showWeaveInfo&gt;
    &lt;Xlint&gt;ignore&lt;/Xlint&gt;
    &lt;encoding&gt;UTF-8&lt;/encoding&gt;
  &lt;/configuration&gt;
  &lt;executions&gt;
    &lt;execution&gt;
      &lt;goals&gt;
        &lt;goal&gt;compile&lt;/goal&gt;
        &lt;goal&gt;test-compile&lt;/goal&gt;
      &lt;/goals&gt;
    &lt;/execution&gt;
  &lt;/executions&gt;
&lt;/plugin&gt;

I have an error on aspectj compile task.

In logs I found a lot of NPE's(264) like that

end public class org.hibernate.metamodel.mapping.ordering.ast.ParseTreeVisitor
 -- (NullPointerException) Cannot invoke &quot;org.aspectj.weaver.ResolvedMember.getGenericParameterTypes()&quot; because the return value of &quot;org.aspectj.weaver.Shadow.getResolvedSignature()&quot; is null
Cannot invoke &quot;org.aspectj.weaver.ResolvedMember.getGenericParameterTypes()&quot; because the return value of &quot;org.aspectj.weaver.Shadow.getResolvedSignature()&quot; is null
java.lang.NullPointerException: Cannot invoke &quot;org.aspectj.weaver.ResolvedMember.getGenericParameterTypes()&quot; because the return value of &quot;org.aspectj.weaver.Shadow.getResolvedSignature()&quot; is null

How to resolve that? Maybe aspectj plugin has an option to skip some weaves if they causes an error or maybe I have to put some properties to resolve that generic parameter types?

Full aspectj compiler log

I don't find any links with same problem in weaving, but there is one with closest exception: link

答案1

得分: 0

感谢您提供的两个MCVE项目。它们帮助我重现了问题,实际上是一个AspectJ问题。在编织器中缺少对某个方法调用的空检查,随后导致在解析切入点中的方法签名时出现错误,指向了编织期间不可用的方法。想象一下,一个call()切入点被编织到一个类中,但后来一个依赖类不可用,或者以不同版本存在,具有不同的方法。这是一个边缘情况,但您遇到了这个问题。

我正在解决这个问题,详见AspectJ问题#243

此外,我为您的项目发送了两个PR:

其中一个项目中您使用了Java 17,因此您应该使用AspectJ Maven插件的AspectJ.dev版本,因为Mojohaus版本的1.14.0仍不支持Java 17。AspectJ项目也推荐使用AspectJ.dev版本,因为它得到更好的维护并具有一些额外的功能。在PR中,我还将AspectJ版本更新到了包含解决您问题的最新快照版本,这样您可以轻松重新测试。这里不重要,但值得一提的是,快照还支持Java 20编译,而最新发布的1.9.19版本仅支持Java 19。


更新: 为了使用AspectJ快照,您需要添加以下存储库:

&lt;repositories&gt;
    &lt;repository&gt;
        &lt;id&gt;ossrh-snapshots&lt;/id&gt;
        &lt;url&gt;https://oss.sonatype.org/content/repositories/snapshots&lt;/url&gt;
        &lt;releases&gt;
            &lt;enabled&gt;false&lt;/enabled&gt;
        &lt;/releases&gt;
        &lt;snapshots&gt;
            &lt;enabled&gt;true&lt;/enabled&gt;
            &lt;updatePolicy&gt;always&lt;/updatePolicy&gt;
        &lt;/snapshots&gt;
    &lt;/repository&gt;
&lt;/repositories&gt;
英文:

Thanks for the two MCVE projects. They helped me to reproduce the problem, and it is actually an AspectJ problem. There are missing null checks for a certain method call in the weaver, which subsequently leads to errors in case of parsing method signatures in pointcuts, pointing to methods unavailable during weaving. Imagine that a call() pointcut is woven into a class, but then a dependency class is unavailable or is present in a different version with different methods. It is an edge case, but you bumped into it.

I am in the process of fixing the problem, see AspectJ issue #243.

Furthermore, I sent you two PRs for your projects:

You are using Java 17 in one of them, so you should use the AspectJ.dev version of AspectJ Maven Plugin, because the Mojohaus version still does not support Java 17 in version 1.14.0. The AspectJ.dev version is also the version recommended by the AspectJ project, because it is better maintained and has a few more features. In the PRs, I also updated the AspectJ version to the latest snapshot containing the fix for your problem, so you can easily retest. Not important here, but FYI, the snapshot also has Java 20 compilation support, while the latest release 1.9.19 only supports Java 19.


Update: In order to use an AspectJ snapshot, you need this repository:

&lt;repositories&gt;
    &lt;repository&gt;
        &lt;id&gt;ossrh-snapshots&lt;/id&gt;
        &lt;url&gt;https://oss.sonatype.org/content/repositories/snapshots&lt;/url&gt;
        &lt;releases&gt;
            &lt;enabled&gt;false&lt;/enabled&gt;
        &lt;/releases&gt;
        &lt;snapshots&gt;
            &lt;enabled&gt;true&lt;/enabled&gt;
            &lt;updatePolicy&gt;always&lt;/updatePolicy&gt;
        &lt;/snapshots&gt;
    &lt;/repository&gt;
&lt;/repositories&gt;

huangapple
  • 本文由 发表于 2023年6月11日 20:14:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/76450431.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定