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。指针

相关文章
相关标签/搜索