线上问题:如何在静态方法中使用自动装配的对象(通过@PostConstruct初始化对象)

1 场景复现

为了在静态方法中使用自动装配的对象,
通过新建对象(new Object())的方式调用自动装配的对象,
但是,执行时使用自动装配的对象时出现空指针,即新建的对象并没有初始化当前类中的自动装配属性。
异常的样例如下:

package com.monkey.standalone.modules.user.service.impl;

import com.monkey.standalone.modules.user.dao.UserDAO;
import com.monkey.standalone.modules.user.service.IUserService;
import com.monkey.standalone.modules.user.vo.BaseUserVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * 用户服务实现类.
 *
 * @author xindaqi
 * @date 2021-05-08 16:01
 */
@Service
public class UserServiceImpl implements IUserService {

    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    @Resource
    UserDAO userDAO;

    public static void testNew() {
        try {
            // 只新建了对象,并没有初始化自动装配的属性:userDAO
            UserServiceImpl userService = new UserServiceImpl();
            // 自动装配的属性userDAO没有初始化,所以userDAO为null
            BaseUserVO baseUserVO = userService.userDAO.queryUserById(1);
            logger.info(">>>>>>>>>User:{}", baseUserVO);
        } catch (Exception ex) {
            logger.error(">>>>>>>User error:", ex);
            throw new RuntimeException(ex);
        }
    }
}

异常信息如下图所示,由异常信息可知,使用自动装配的属性userDAO时出现空指针。
在这里插入图片描述

2022-11-13 21:11:36,654 ERROR [traceId=, spanId=] 2022-11-13 21:11:36 [http-nio-9122-exec-4] [ERROR] - >>>>>>>User error:
java.lang.NullPointerException: null
at com.monkey.standalone.modules.user.service.impl.UserServiceImpl.testNew(UserServiceImpl.java:46)
at com.monkey.standalone.api.UserApi.queryUserById(UserApi.java:65)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)

2 原因

通过new新建对象后,并没有初始化对应的属性:userDAO,所以userDAO属性为null,
无法使用该属性对应的其他所有功能。
@Service初始化相关对象时,会交由Spring容器管理,
因此,@Resoure会自动获取Spring会初始化相关对象,userDAO才会生效,
而使用new新建的对象并不会托管给Spring,所以,其他的属性不会自动初始化。

3 方案

为解决新建对象后相关属性为null的问题,需要在新建对象后初始化相关属性。
为了获取已装配的对象,就要在当前类完成依赖注入之后,执行相关的初始化操作,
而@PostConstructor正是在执行依赖注入之后执行初始化操作的注解,@PostConstruct部分注释如下图所示:
在这里插入图片描述

使用@PostConstruct后处理(装配)静态对象。
在当前类中构建静态的当前类属性,
使用@PostConstruct初始化静态的当前类属性,并初始化需要使用的已装配的对象,
完整测试样例如下:

package com.monkey.standalone.modules.user.service.impl;

import com.monkey.standalone.modules.user.dao.UserDAO;
import com.monkey.standalone.modules.user.service.IUserService;
import com.monkey.standalone.modules.user.vo.BaseUserVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

/**
 * 用户服务实现类.
 *
 * @author xindaqi
 * @date 2021-05-08 16:01
 */
@Service
public class UserServiceImpl implements IUserService {

    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    public static UserServiceImpl userServiceImpl;

    @Resource
    UserDAO userDAO;

    @PostConstruct
    public void init() {
        userServiceImpl = this;
        // 初始化已自动装配的对象
        userServiceImpl.userDAO = this.userDAO;
    }

    public static void testAutowired() {
        // 通过静态的当前类属性获取相关方法
        BaseUserVO baseUserVO = userServiceImpl.userDAO.queryUserById(1);
        logger.info(">>>>>>>>>User:{}", baseUserVO);
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天然玩家

坚持才能做到极致

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值