IOTXING

记录技术学习之路

0%

Spring注入变量为null

背景

有个controller,里面有个方法,在使用public修饰的时候,能够拿到类中定义的属性,在使用private的时候,取到的属性为null

调查

为public的时候,调试信息如下

public

其中的this对象,是正常的controller对象,并且agentBizService能够拿到正常的值,工作正常

当为private的时候,调试信息如下

private

能够发现this对象明显不一样。并且agentBizService 为null。

调查

SpringBoot 默认使用了Cglib进行方法的代理,进而实现代码的增强。

cglib的动态代理,是通过生成类继承于目标类,然后在实际执行代码的时候,调用的是代理后的类,进而实现了代码增强。

如果使用的是private的方法的话,对代理类来说,是看不到这个方法的,因为就没法通过代理来实现功能增强。

对于Spring来说,不管什么样的方法,都会走到下面这一步

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class DelegatingMethodAccessorImpl extends MethodAccessorImpl {
private MethodAccessorImpl delegate;

DelegatingMethodAccessorImpl(MethodAccessorImpl var1) {
this.setDelegate(var1);
}

public Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException {
return this.delegate.invoke(var1, var2); //通过这一步进行反射
}

void setDelegate(MethodAccessorImpl var1) {
this.delegate = var1;
}
}

如果是方法被代理类处理了,在执行invoke之后,会进入到Cglib的intercept方法,进而进行一些代理增强的处理。

如果没有被代理,那么在调用invoke之后,会直接进入到对应的方法。由于spring对bean都是统一进行管理的,而且是通过代理反射来实现依赖的处理。如果是直接执行对应的方法,就会导致对应的bean没有被注入,也就是null值。

总结

因为使用了private方法,导致方法无法通过AOP的方式增强,进而无法获取到Spring的bean信息,所有使用依赖注入的变量都无法被获取到