【问题标题】:Add AspectJ in Webservice在 Web 服务中添加 AspectJ
【发布时间】:2017-05-10 14:30:33
【问题描述】:

我有一个 Java EE Web 服务 (REST),现在想使用 AspectJ 创建一个规则,该规则将打印出每个传入的服务调用及其参数。

我刚刚阅读了这个tutorial 并实现了以下代码:

POM.XML

        <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>1.8.10</version>
    </dependency>
    
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.10</version>
    </dependency>
    
</dependencies>
<build>
  <plugins>
    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>aspectj-maven-plugin</artifactId>
        <version>1.7</version>
        <configuration>
            <complianceLevel>1.8</complianceLevel>
            <source>1.8</source>
            <target>1.8</target>
            <showWeaveInfo>true</showWeaveInfo>
            <verbose>true</verbose>
            <Xlint>ignore</Xlint>
            <encoding>UTF-8 </encoding>
        </configuration>
        <executions>
            <execution>
                <goals>
                    <!-- use this goal to weave all your main classes -->
                    <goal>compile</goal>
                    <!-- use this goal to weave all your test classes -->
                    <goal>test-compile</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
</plugins>

...并创建了一个 Test.aj 文件,其中有一个切入点,在调用 getSignOfLife() 后应该打印出一个测试字符串:

import de.jack.businesspartner.service.BusinessPartnerServiceImpl;
public aspect TestAspectJ {

    pointcut getSignOfLife() : 
      call(void BusinessPartnerServiceImpl.getSignOfLife());

    before() : getSignOfLife() {
        System.err.println("ADKL TEST ASPECT");
    }

}

--> 但是如果我调用 getSignOfLife() 方法,什么都不会发生。你能帮帮我吗?

【问题讨论】:

  • 您是从 IDE 运行您的应用程序,还是创建一个 .war 文件并将其部署到某个应用程序服务器/servlet 容器?
  • 我用我的 IDE 创建了一个 .war 文件,并将它部署到我的 wildfly 应用服务器。但是如果我调用 getSignOfLife() 方法,则不会调用方面...
  • 你用什么做服务器?
  • 您的 Wildfly 服务器的配置和版本是什么?

标签: java web-services maven aspectj


【解决方案1】:

你的切入点表达可能是错误的:

pointcut getSignOfLife() : 
  call(void BusinessPartnerServiceImpl.getSignOfLife());

call 中的表达式应该与你的真实方法的签名相匹配。

检查清单

  • 返回类型:getSignOfLife好像有返回值,你在表达式中写一个void返回类型,会匹配失败;
  • 参数类型:你可以用f(..)来表示一个方法f带任何参数,但如果你留空,则表示没有参数。如果你的实际方法有参数,匹配失败;
  • 注意intInteger的表达方式不同,因为原语和装箱类型不同;
  • 你的 pom 中需要 maven 的原始编译器插件;

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>
    

更多

  • 如果你想深入AspectJ,可以参考here
  • 在最常见的情况下,Spring AOP 足以处理日志、身份验证等工作,可以与注释一起使用,我认为更方便。
  • Runnable code

【讨论】:

    【解决方案2】:

    @Tony 解释得很好。

    关于你指出的tutorial,我通过稍微修改帐户方面进行了测试:

    public aspect AccountAspect {
        final int MIN_BALANCE = 10;
    
        pointcut callWithDraw(int amount, Account acc) : 
         call(boolean Account.withdraw(int)) && args(amount) && target(acc);
    
        before(int amount, Account acc) : callWithDraw(amount, acc) {
        }
    
        boolean around(int amount, Account acc) : 
          callWithDraw(amount, acc) {
            acc.balance -= 5;
            if (acc.balance < amount) {
                return false;
            }
            return proceed(amount, acc);
        }
    
        after(int amount, Account balance) : callWithDraw(amount, balance) {
            System.out.println("After withdraw " + amount);
        }
    }
    

    然后在一个简单的 servlet 中:

    @WebServlet("/Hello")
    public class Hello extends HttpServlet {
    
        /**
         * 
         */
        private static final long serialVersionUID = 482093033327453159L;
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            Account acc = new Account();
            resp.setContentType("text/html");
            PrintWriter out = resp.getWriter();
            out.println("Account before withdraw: " + acc.balance + "<br/>");
            acc.withdraw(10);
            out.println("Account after withdraw: " + acc.balance + "");
            out.close();
        }
    }
    

    我用过:

    • Java 8
    • Wildfly 10.1.0.Final

    它按预期工作(当调用withdraw时,帐户被提现了5个,正如您在我的aspectj文件中的around中看到的那样,并且打印在控制台上)

    【讨论】:

      猜你喜欢
      • 2011-06-13
      • 1970-01-01
      • 1970-01-01
      • 2011-01-23
      • 2011-06-25
      • 2011-10-10
      • 1970-01-01
      • 1970-01-01
      • 2015-04-23
      相关资源
      最近更新 更多