当AOP @pointcut切入FunctionalInterface时,为什么会引发NullPointException?

时间:2018-06-15 15:49:11

标签: java nullpointerexception aop functional-interface

今天我遇到了NullPointExcepiton当我尝试在java中使用AOP Logger来打印包含BiPredicate(FuncionalInterface)的类的日志时。

问题:

  

使用AOP的FunctionalInterface是否有错误用法?

     

当我将pointCut设置为BiPredicateExample.java时,异常将会   由biPredicateExample.cmp(FuntionalInterface)引发,而   这个类中的方法很有趣(biPredicateExample.cmp1())。

可以使用以下代码复制NullPointExcepiton:

Github repository link here

COM /测试/ BiPredicateExample.java

import org.springframework.stereotype.Component;
import java.util.function.BiPredicate;

@Component
public class BiPredicateExample {

    public BiPredicate<Integer,Integer> cmp = (x,y) -> (x>y);

    public boolean cmp1(Integer x, Integer y){
        return x>y;
    }
}

COM /记录器/ BiPredicateExample.java

package com.logger;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LogAspect {

    /**
     * BiPredicateExample works fine.
     */
//    @Pointcut("execution(* com.empty.*.*(..) )")

    /**
     *  It'll raise NullPointException When this PointCut cut
     *  into the FunctionalInterface.
     */
    @Pointcut("execution(* com.test.*.*(..) )")
    public void logPointCut(){}

    @Before("logPointCut()")
    public void printBeforeMethodInvoke(JoinPoint joinPoint){

    }

}

COM / Application.java

package com;

import com.test.BiPredicateExample;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication
public class Application implements CommandLineRunner{
    @Autowired
    BiPredicateExample biPredicateExample;

    public static void main(String[]args){
        SpringApplication.run(Application.class,args);
    }

    @Override
    public void run(String... strings) throws Exception {

        boolean w=biPredicateExample.cmp1(10,2);
        System.out.println(w);

        boolean f=biPredicateExample.cmp.test(10,2);
        System.out.println(f);
    }
}

谢谢!

我的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>groupId</groupId>
    <artifactId>AOP_FunctionalInterface_Test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
            <version>2.0.3.RELEASE</version>
        </dependency>
    </dependencies>>


</project>

1 个答案:

答案 0 :(得分:0)

问题是成员变量cmp在原始类中只有一个有意义的值,但是一旦使用Spring AOP,您实际上就是在与动态代理对象进行交互。但是,JDK动态代理仅代理公共方法调用(CGLIB也是受保护的和包范围的方法)。成员变量没有代理机制,您需要确保不通过外部成员访问直接访问内部状态,例如通过getter方法。

即。在这种情况下,您将biPredicateExample.cmp更改为biPredicateExample.getCmp(),即全部:

package com.test;

import org.springframework.stereotype.Component;

import java.util.function.BiPredicate;

@Component
public class BiPredicateExample {
  private BiPredicate<Integer, Integer> cmp = (x, y) -> (x > y);

  public boolean cmp1(Integer x, Integer y) {
    return x > y;
  }

  public BiPredicate<Integer, Integer> getCmp() {
    return cmp;
  }
}
package com;

import com.test.BiPredicateExample;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application implements CommandLineRunner {
  @Autowired
  BiPredicateExample biPredicateExample;

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }

  @Override
  public void run(String... strings) throws Exception {
    System.out.println(biPredicateExample.cmp1(10, 2));
    System.out.println(biPredicateExample.getCmp().test(10, 2));
  }
}
package com.logger;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LogAspect {
  @Pointcut("execution(* com.test..*(..) )")
  public void logPointCut() {}

  @Before("logPointCut()")
  public void printBeforeMethodInvoke(JoinPoint joinPoint) {
    System.out.println(joinPoint);
  }
}

然后控制台日志变为:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.3.RELEASE)

2018-06-16 14:15:10.040  INFO 12456 --- [           main] com.Application                          : Starting Application on Xander-Ultrabook with PID 12456 (C:\Users\alexa\Documents\java-src\AOP_FunctionalInterface_Test\target\classes started by alexa in C:\Users\alexa\Documents\java-src\AOP_FunctionalInterface_Test)
2018-06-16 14:15:10.056  INFO 12456 --- [           main] com.Application                          : No active profile set, falling back to default profiles: default
2018-06-16 14:15:10.118  INFO 12456 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@3c87521: startup date [Sat Jun 16 14:15:10 ICT 2018]; root of context hierarchy
2018-06-16 14:15:11.437  INFO 12456 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2018-06-16 14:15:11.452  INFO 12456 --- [           main] com.Application                          : Started Application in 1.724 seconds (JVM running for 2.524)
execution(boolean com.test.BiPredicateExample.cmp1(Integer,Integer))
true
execution(BiPredicate com.test.BiPredicateExample.getCmp())
true
2018-06-16 14:15:11.452  INFO 12456 --- [       Thread-5] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@3c87521: startup date [Sat Jun 16 14:15:10 ICT 2018]; root of context hierarchy
2018-06-16 14:15:11.531  INFO 12456 --- [       Thread-5] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown

Process finished with exit code 0