spring中,子类初始化父类属性,父类使用这个属性却是NULL,为什么?

四个class类似如下

public abstract class DefaultSimpleFirmwareServiceImp implements SimpleFirmwareService {
        private JVMCacheWrap<Map<Integer, List<SimpleFirmware>>> firmwareCache;
        protected abstract SimpleFirmwareRepository getFirmwareRepository();

        protected final JVMCacheWrap<Map<Integer, List<SimpleFirmware>>> getCache() {
                return firmwareCache;
        }

        protected final void initService(String moduleKey, int[] hardwares) {
                firmwareCache = JVMCacheFactory.create(balabala...);
        }

        public abstract void init();
       
        public final void saveFirmware(SimpleFirmware firmware) throws Exception {
                getFirmwareRepository().saveFirmware(firmware);
                getCache().stale();
        }
}

@Component
@Qualifier("goFirmwareService")
public class GoFirmwareServiceImp extends DefaultSimpleFirmwareServiceImp implements GoFirmwareService {

        @Override
        protected SimpleFirmwareRepository getFirmwareRepository() {
                return balabala...;
        }
        @Override
        @PostConstruct
        public void init() {
                initService("go", new int[] { 1 });
        }
}


public abstract class SimpleFirmwareAdminAction extends BaseAction {
        protected abstract SimpleFirmwareService findFirmwareService();

        public String firmware_save() throws Exception {
                findFirmwareService().saveFirmware(getParameterBean(new SimpleFirmware()));
                return NONE;
        }

        balabala...
}

@Controller
public class GoAdminAction extends SimpleFirmwareAdminAction {
        private static final long serialVersionUID = 6955716525662800331L;
        @Autowired
        private GoFirmwareService goFirmwareService;

        @Override
        protected SimpleFirmwareService findFirmwareService() {
                return goFirmwareService;
        }

        balabala...
}

structs 调用 GoAdminActionfirmware_save 的方法,最终调用了DefaultSimpleFirmwareServiceImp.saveFirmware方法,但是getCache()方法返回了NULL,出现了空指针异常
但是initServiceGoFirmwareServiceImp在初始化的时候调用了,firmwareCache的值不应该为空
没有setCache方法,所以不会出现其他地方又置为NULL的情况

应该不是父类属性修饰符的问题
图片描述

DEBUG部分截图

  • GoFirmwareServiceImp.init()调用了DefaultSimpleFirmwareServiceImp.initService()方法

图片描述

  • GoFirmwareServiceImp.init()调用结束

图片描述

  • 向API发送数据,Controller的SimpleFirmwareAdminAction.firmware_save()方法被调用

图片描述

  • SimpleFirmwareAdminAction.firmware_save()方法调用子类的GoAdminAction findFirmwareService()的方法

图片描述

  • 然后findFirmwareService()返回了service,并调用了DefaultSimpleFirmwareServiceImp. saveFirmware()方法,该方法调用了getCache方法,出现了NULL,如图

图片描述

阅读 10.7k
5 个回答

由于cglib代理原因导致的,解决方法是 原来的protected final改为public就OK了,只改修饰符为public不行。

因为这句private JVMCacheWrap<Map<Integer, List<SimpleFirmware>>> firmwareCache;,你使用了private的可见性,而对于private父子类是不会共享的,也就是说父类有一份,子类也有一份,你在初始化的时候是初始化了子类的这个属性,然而到了你使用的时候,getCache方法返回的是父类的cache,所以为空,可以把private换成protected,应该就可以了

initService()方法里面打印下类的hashcode.
getCache()方法里面也打印下类的hashcode.

System.out.println(this);

看看是不是同一个实例。

谢邀,因为这个代码:

@Override

    @PostConstruct
    public void init() {
            initService("go", new int[] { 1 });
    }

在@Autowired的GoFirmwareService实例化之后执行,所以你在执行init()之前调用getCache()返回空值。

父类属性 修饰词 导致的吧

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题