栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring-Bean的作用域-Prototype

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring-Bean的作用域-Prototype

Spring-Bean的作用域-Prototype 一、Prototype

非单一原型范围导致每次对特定 bean 发出请求时都会创建一个新 bean 实例。也就是说,bean 被注入到另一个 bean 中,或者通过getBean()容器上的方法调用来请求它,都是返回一个全新的对象实例。

通常,应该对所有有状态 bean 使用原型作用域,对无状态 bean 使用单例作用域。

与其他作用域相比,Spring并不管理原型bean的完整生命周期。容器实例化、配置和组装一个原型对象,并将其传递给客户端,而不需要进一步缓存该原型实例。因此,尽管初始化生命周期回调方法在所有对象上都被调用,而不管作用域如何,但在原型的情况下,配置的销毁回调方法不会被调用。客户端代码必须清理原型作用域对象,并释放原型bean所持有的资源。要让Spring容器释放由原型作用域bean持有的资源,需要使用自定义bean后处理器,它保存了对需要清理的bean的引用。

看起来,似乎比单例模式要复杂,因为这种方式会不断创建实例,如果不进行清除,最终会导致资源耗尽

二、应用场景
  • 代替new 实例化对象
  • 资源不可共享,保证资源的安全性(某些情况下,需要每次获得处于某个状态的对象,但在每次使用后状态会发生变化)
三、基于XML

声明一个实体类



请求多个实例


	
	
	


这样子将获得三个不同的实例

这里需要注意的是:对于大局来说,每个请求获得的仍是一个实例,因为prototypeService是单例的

四、基于注解

创建一个实体类(或者其他有状态的对象)

public class PrototypeEntity {

    private int flag = 0;

    public int getFlag() {
        return flag;
    }

    public void setFlag(int flag) {
        this.flag = flag;
    }

}

创建service类,这个类中有一个属性,以及一个方法,每次调用这个方法将会进行自增。并声明他的prototype作用域

@Service
public class PrototypeService {

    @Autowired
    private PrototypeEntity one;
    @Autowired
    private PrototypeEntity two;
    @Autowired
    private PrototypeEntity three;

    public String getProto() {
        one.setFlag(one.getFlag() + 1);
        two.setFlag(two.getFlag() + 1);
        three.setFlag(three.getFlag() + 1);
        return "one:"+one.getFlag()+"ntwo:"+two.getFlag()+"three:"+three.getFlag()+"n";
    }

  
    @Bean
    @Scope("prototype")
    public PrototypeEntity prototypeEntity(){
        return new PrototypeEntity();
    }
}

在Controller进行请求注入Service

@RestController
public class PrototypeController {

    @Autowired
    private PrototypeService prototypeService;

    @RequestMapping("/getProto")
    public String getProto(){
       return  prototypeService.getProto();
    }
}

最后启动项目,在浏览器访问 http://ip:port/getProto ,看到浏览器返回的内容也许会有疑惑,“这不还是会在原有基础上自增吗?”

没错,这也就是前面所提到的在大局上来说,每个PrototypeEntity仍是单例的。(这涉及到单例注入原型的问题,以后会说明)

如果还察觉不出和Singleton的区别,你可以尝试把@Scope(“prototype”)去掉

	
	@Bean
    public PrototypeEntity prototypeEntity(){
        return new PrototypeEntity();
    }

将会以+3的形式递增,因为每次请求的是同一个实例

可以将Controller和Server的作用域都声明为原型,这样每次整条链路都是新的实例,更多的应用可以自由发挥。

最后

当使用具有对原型 bean 的依赖的单例作用域 bean 时,请注意在实例化时解析依赖关系。因此,如果您将原型范围的 bean 依赖注入到单例范围的 bean 中时,则会实例化一个新的原型 bean,然后将依赖项注入到单例 bean 中。原型实例是唯一提供给单例作用域 bean 的实例。

但是,假设希望单例范围的 bean 在运行时重复获取原型范围的 bean 的新实例。不能将原型范围的 bean 依赖注入到您的单例 bean 中,因为该注入仅发生一次,当 Spring 容器实例化单例 bean 并解析并注入其依赖项时。(想在单例bean中获取原型的bean可以通过方法注入的方式去使得每次获取的原型bean是一个新的)

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/667233.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号