spring单例、多例使用方法

今天聊聊单例和多例。只想看spring管理的实例有哪些模式,直接看最后。

相信大部分使用java 做web开发的开发人员都用过spring。spring功能最基础功能就是IoC(Inversion of control——控制反转)、AOP(Aspect Oriented Programming——面向切面编程)。其中IoC核心是DI(Dependency injection——依赖注入)。

我们最开始写项目自然而然的是没有框架,生写!但代码多了之后,发现有很多代码,可以抽成公共方法。有些又可以抽成一个类。而有些类又是贯穿整个项目生命周期始终的,而且往往这些类的初始化方法很复杂且重要。那怎么办,总不能每次使用的时候初始化一遍吧,这样很耗编码时间不说,还很占用计算机性能。于是,工厂模式应运而生。通过工厂模式获取各个重要的实例对象。这样就带来一个问题,怎样保证实例只创建一次呢?单例模式应运而生。于是,我们常用的框架spring就成了。

然而需求的发展往往不是单一技术能很好解决的。单例、依赖注入固然好。但是也让我们的开发模式陷入一种定式。即controller、service、dao这样虽然是快速规范的划分,但是往往一些复杂的逻辑只在service或者controller中写会有大量的私有方法、或者一个方法几百上千行。整个业务操作的生命周期局限在一个方法内。并不能好好利用面向对象的思想,写到最后完全就是面向过程编程。一旦逻辑复杂,那方法写的简直惨不忍睹,而且局限于方法的生命周期,很多参数可能会多次调用数据库查同一个数据。那么有什么办法能改变这个局面呢?历史总会给我们答案。

自新世纪之初提出“领域驱动设计”(DDD)以来,这玩意一直不受重视,不仅玄之又玄的理论很少有人去专研,而且所谓“敏捷开发”的盛行,也不适合DDD。但这里并不介绍DDD,说一说DDD的充血模型要在传统数据驱动的业务中使用将面临的首要问题——单例如何注入进充血模型。

比如,我有个User对象,而对象的保存查询操作是与数据库操作。我并不想让User是一个干瘪的值对象,而是让他具备行为,是一个真正有血有肉的充血模型。那么saveUser(User)这样的方法就不再由Dao提供,而是应该由user.save()替代。熟悉JPA的同学肯定想到了。jpa支持对象操作替代传统的repository操作。例如典型的user中的List<Role> roles属性作为关联查询的属性。如果设置级联查询为懒加载,那么jpa只在调用user.getRoles()方法执行的时候发送sql查询对应的role。这是因为jpa代理了user实体对象,而且这也有个问题。如果被jpa代理的对象调用toString()方法,获取roles属性打印时会触发jpa操作。但这时可能已经不属于jpa Entity的生命周期了。踩过坑的朋友肯定遇到过打印日志报了莫名的jpa异常,百思不得其解吧。

况且我们想要的不只是这些。我们可能有些其他的被sqring单例管理的对象方法需要在不同的实例对象中使用。例如:user想要发送数据到远程。那么user.send()可就不归jpa管了。此时如果要想让user能做这个事情必然只能通过spring上下文获取被spring管理的类。聪明的小伙肯定想到了。我让user也被spring管理起来,不就可以注入了吗?是的,但是一旦被spring管理默认就是单例的。总不能每个user都是同一个吧。其实spring可以设置多例的,只是用的人很少。在有@componet之类注解(@service、@bean...等)受spring管理的类上再加上注解@scope(“prototype”)那么被spring管理的类就是多例的。稍微麻烦点的是,要想获取多例必须通过spring上下文获取。如果直接注入,那么注入的user还是只是那一个。相信各位一定都看过@scope(“prototype”)这种写法吧。但spring其实提供了常量,@scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE),常量可以防止写错那长串单词。有了多例,我们有血有肉的User对象写起来就方便了许多。

为什么我们要这么做呢?“把权力关进笼子”,这句话在编程界就是强类型、常量、枚举这些来体现的。同样,DDD也是把权力锁进领域对象。避免随心所欲的service、随心所欲的repository导致代码后期维护成为爬“屎山”。

spring支持的模式:

1.ConfigurableBeanFactory.SCOPE_SINGLETON——单例

2.ConfigurableBeanFactory.SCOPE_PROTOTYPE——多例

扩展模式:

3.WebApplicationContext.SCOPE_APPLICATION

4.WebApplicationContext.SCOPE_GLOBAL_SESSION

5.WebApplicationContext.SCOPE_SESSION

6.WebApplicationContext.SCOPE_REQUEST

以上扩展模式看名字都能明白不做多介绍了。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值