這兩天作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。指針