@Scope失效问题

单例的Bean注入其它类型的@Scope属性有可能会失效,针对失效的情况,我们可以采取四种解决办法。

一.失效场景

1.准备多例Bean

java 复制代码
package com.example.springdemo.demos.a27;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/**
 * @author zhou
 * @version 1.0
 * @description TODO
 * @date 2025/10/15 21:56
 */
@Scope("prototype")
@Component
public class F1 {
}

2.E中注入F1

java 复制代码
package com.example.springdemo.demos.a27;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

/**
 * @author zhou
 * @version 1.0
 * @description TODO
 * @date 2025/10/15 21:56
 */
@Component
public class E {
    @Autowired
    private  F1 f1;
    public F1 getF1(){
        return f1;
    }
}

3.容器中获取对象

java 复制代码
package com.example.springdemo.demos.a27;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

/**
 * @author zhou
 * @version 1.0
 * @description TODO
 * @date 2025/10/15 21:54
 */
@ComponentScan("com.example.springdemo.demos.a27")
public class a27Application {
    private static final Logger log = LoggerFactory.getLogger(a27Application.class);

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(a27Application.class);
        E e = context.getBean(E.class);
        log.info("{}",e.getF1().getClass());
        log.info("{}",e.getF1());
        log.info("{}",e.getF1());
        log.info("{}",e.getF1());

    }
}

结果:

通过依赖注入的F1对象多次获取后都是同一个,Scope作用失效了。分析其原因是对于单例对象E来讲,依赖注入仅仅发生了一次,后续再也没有使用多例的F1,所以多次获取都是同一个对象。

二.解决办法

下面提供四种解决方法。

1.添加@Lazy注解

java 复制代码
package com.example.springdemo.demos.a27;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

/**
 * @author zhou
 * @version 1.0
 * @description TODO
 * @date 2025/10/15 21:56
 */
@Component
public class E {
    @Lazy
    @Autowired
    private  F1 f1;
    public F1 getF1(){
        return f1;
    }
}

结果每次获取出不同的F1对象。使用@Lazy注解之后,注入便是F1的代理对象(注意看输出的F1对象的类型),e.getF1()使用了F1代理类的toString(),而每次使用代理对象的方法都会创建新的F1对象。

2.在Scope属性中设置proxyMode

设置proxyMode的值为ScopedProxyMode.TARGET_CLASS,可以为F1对象生成代理对象,与上面方法类似。

java 复制代码
package com.example.springdemo.demos.a27;

import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;

/**
 * @author zhou
 * @version 1.0
 * @description TODO
 * @date 2025/10/15 21:56
 */
@Scope(value = "prototype",proxyMode = ScopedProxyMode.TARGET_CLASS)
@Component
public class F1 {
}

3.使用ObjectFactory包装F1

java 复制代码
package com.example.springdemo.demos.a27;

import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

/**
 * @author zhou
 * @version 1.0
 * @description TODO
 * @date 2025/10/15 21:56
 */
@Component
public class E {
    @Autowired
    private ObjectFactory<F1> f1;
    public F1 getF1(){
        return f1.getObject();
    }
}

通过这种方式每次获取F1,工厂都可以生成多例对象。

4.注入ApplicationContext容器

每次从容器中获取F1对象自然是多例的。

java 复制代码
package com.example.springdemo.demos.a27;

import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

/**
 * @author zhou
 * @version 1.0
 * @description TODO
 * @date 2025/10/15 21:56
 */
@Component
public class E {
    @Autowired
    private ApplicationContext context;
    public F1 getF1(){
        return context.getBean(F1.class);
    }
}
相关推荐
DongQiShanRen9 小时前
裁决台账双向互校(上):名册与实物的第一道对账
java·linux·运维·数据库·人工智能·自然语言处理·数据挖掘
潼心1412o9 小时前
C++初阶(长期更新)第9讲:string(上)
开发语言·c++
朝朝辞暮i9 小时前
C++ 第 39 章: 阶段性总复习——类、对象、构造、继承、this、指针与智能指针
开发语言·c++·算法·ros2
cpolar技术支持9 小时前
Spring Boot 接口本地正常,异地前端却报跨域?用 cpolar 跑通 CORS 预检与白名单
java·springboot·cpolar·前后端分离·cors
wuminyu9 小时前
Virtual Thread重投递至ForkJoinPool任务队列过程解析
java·linux·c语言·jvm·c++
小蒜学长9 小时前
在线保险服务与管理平台的设计与实现(代码+数据库+LW)
java·数据库·spring boot·后端·服务平台·在线保险
掉进电商坑三年没爬出来的东叔10 小时前
青龙面板进阶:一个面板聚合多平台签到,所有积分自动领
java·开发语言
iCxhust10 小时前
51单片机电力载波应用开发(七)广播通讯
c语言·开发语言·单片机·嵌入式硬件·51单片机
殷色玫瑰10 小时前
C++ STL:stack、queue、priority_queue 与容器适配器详解
java·开发语言·数据结构·c++·算法·visualstudio
IT方大同11 小时前
java输入输出+方法
java·开发语言·python