记一次接入websocket过程中@ServerEndpoint和@Scope(“prototype“)、@Autowire、@Postconstruct一起使用不生效的原因分析

本文分析了一次在使用WebSocket时遇到的问题:@ServerEndpoint、@Scope("prototype")、@Autowire和@PostConstruct一起使用时,依赖注入失效且初始化方法未执行。通过研究源码,发现原因是WebSocket连接创建的新对象不受Spring管理,导致依赖注入失败和初始化方法未执行。解决方案是调整对象创建和依赖注入的方式。
摘要由CSDN通过智能技术生成

使用场景

最近在做直播业务,服务端需要与客户端建立长连接进行通信,所以我选择在项目使用websocket,具体如何使用这里不做详细介绍,直接上代码:

@ServerEndpoint(value = "/websocket/{userId}")
@Component
@Scope(value = "prototype")
public class WebsocketServer {
   
	@Autowired
    private UserManager userManager;
    
    @PostConstruct
    public void init() {
   
        logger.info("init success");
    }
    .....
}

复现结果

@Postconstruct方法代表在项目初始化时,执行备注的方法(无论单例还是多例)。但是这里并没有执行init方法
而且当客户端创建websocket连接后,在服务端onOpen方法打断点发现,userManager为null

探究原因

一开始我在想是不是设置了@Scope(“prototype”)导致的,便去查看了一下IOC源码,依赖注入的代码如下:

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
   
        if (bw == null) {
   
            if (mbd.hasPropertyValues()) {
   
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
            }
        } else {
   
            if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
   
                Iterator var4 = this.getBeanPostProcessors().iterator();

                while(var4.hasNext()) {
   
                    BeanPostProcessor bp = (BeanPostProcessor)var4.next();
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
   
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                        if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
   
                            return;
                        }
                    }
                }
            }

            PropertyValues pvs = mbd.hasPropertyValues() ? mbd.getPropertyValues() : null;
            int resolvedAutowireMode = mbd.getResolvedAutowireMode();
            if (resolvedAutowireMode == 1 || resolvedAutowireMode == 2) {
   
                MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);
                if (resolvedAutowireMode == 1) {
   
                    this.autowireByName(beanName, mbd, bw, newPvs);
                }

                if (resolvedAutowireMode == 2) {
   
                    this.autowireByType(beanName, mbd, bw, newPvs);
                }

                pvs = newPvs;
            }

            boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
            boolean needsDepCheck = mbd.getDependencyCheck() != 0;
            PropertyDescriptor[] filteredPds = null;
            if (hasInstAwareBpps) {
   
                if (pvs == null) {
   
                    pvs = mbd.getPropertyValues();
                }

                Iterator var9 = this.getBeanPostProcessors().iterator();

                while(var9.hasNext()) {
   
                    BeanPostProcessor bp = (BeanPostProcessor)var9.next();
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
   
                        InstantiationAwareBeanPostProcessor ibp = (
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值