今天我遇到了NullPointExcepiton当我尝试在java中使用AOP Logger来打印包含BiPredicate(FuncionalInterface)的类的日志时。
问题:
使用AOP的FunctionalInterface是否有错误用法?
当我将pointCut设置为BiPredicateExample.java时,异常将会 由biPredicateExample.cmp(FuntionalInterface)引发,而 这个类中的方法很有趣(biPredicateExample.cmp1())。
可以使用以下代码复制NullPointExcepiton:
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>
答案 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