这两天作aop切面日志时,发现private方法报空指针。
原切入点配置以下:java
@Pointcut("@within(org.springframework.web.bind.annotation.RestController)") public void logPoint(){ };
当某个Controller类中含有private方法,而且该类有须要spring注入的对象时,且在该私有方法有中使用spring注入的对象时会报空指针。
那么为何会报空指针了。我们看一下动态代理的过程,这里使用的是cglib代理。web
Enhancer enhancer = new Enhancer(); enhancer.setCallback(new MyInteceptor()); enhancer.setSuperclass(A1.class); A1 proxy = (A1)enhancer.create();
上面是一个建立cglib代理的类。
这里有一点要记住,private和final修饰的方法,不会被代理。也就是说private和final的方法不会进入callBack。若是进入不了callBack,那么就进入不了被代理的目标对象。那么只能在proxy对象上执行private或final修饰的方法。而proxy对象是由cglib实例化的,里面没有spring注入的对象。因些报空指针。spring
看个示例:
这是一个A1类,里面有一个say1的私有方法。ide
public class A1 { public void say(){ System.out.println("say"); say1();; } private void say1(){ System.out.println("say1"); } private void say2(){ System.out.println("say2"); } void say3(){ System.out.println("say3"); } }
这里A类,包含callBack代理
public class A { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\code"); Enhancer enhancer = new Enhancer(); enhancer.setCallback(new MyInteceptor()); enhancer.setSuperclass(A1.class); A1 proxy = (A1)enhancer.create(); System.out.println(proxy.getClass()); Method[] ms = proxy.getClass().getMethods(); proxy.say();; Method method = A1.class.getDeclaredMethod("say2",null); method.setAccessible(true); method.invoke(proxy,null); System.out.println("ok"); } static class MyInteceptor implements MethodInterceptor { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("before:"+method.getName()); Object obj = methodProxy.invokeSuper(o,objects); System.out.println("after:"+method.getName()); return null; } } }
运行后say2没有被代理,也就是说没有进入callBack。 相同的方式经过反射获取say方法,能够进入callBack。指针