spring aop 代理private方法 報錯的問題分析

spring aop 代理private方法報空指針的問題

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

相關文章
相關標籤/搜索