Spring AOP默认使用cglib,会生成目标对象的子类代理对象。调用目标对象的方法,实际上是调用代理对象的方法。由于子类能够继承父类的方法,因此一般情况下目标类的方法,代理对象都会有。但是当目标类中某个方法带有final关键字时,这个方法不能被重写,因此代理对象中没有这个方法,因此会调用目标对象的方法。
比如以下代码:
@Service public class Car{ @Autowired Engine engine; public final Engine getEngine() { return this.engine; } public void setEngine(Engine engine) { this.engine = engine; } }
Car类中有一个spring自动注入的engine对象。当我们调用car.getEngine()方法时,发现返回值为空。而我们setEngine之后返回值仍为空。这是因为get方法前带有final关键字,因此调用的是目标对象的get方法,而目标对象中并没有engine对象,而set没有final,因此调用的是代理对象,因此每次set其实是把engine对象注入到了代理对象中,目标对象中的engine仍为空。如果把setEngine方法前也加上final,那么set时调用的就是目标对象,因此再次get就不为空了。
但是,如果通过一个不带final的方法间接调用final方法,是可以的。比如把上边的代码改成这样:
@Autowired Engine engine; public final Engine getEngine() { return this.engine; } public void setEngine(Engine engine) { this.engine = engine; } public Engine getEngineWithoutFinal() { return getEngine(); }可以看到,getEngineWithoutFinal方法实际上是调用的带有final关键字的getEngine方法,但是getEngineWithoutFinal返回的不是null,而直接调用getEngine方法仍为null