ActFramework - 控制器单例还是多例

控制器是 MVC 框架的核心组件,应用程序控制器的方法处理 HTTP 请求。这里首当其冲需要回答的一个问题就是控制器的实例应该是单例 (Singleton)还是就每个请求生成新的实例。

不同的框架对此有不同的处理方式,SpringMVC 的控制器采用单例;Struts 的 Action 则是多实例;PlayFramework v1.x 的方式比较极端,控制器方法必须是静态的,因此不需要生成实例。

ActFramework 生成控制器实例的方式与众不同,没有统一的单例或者多例的限制,而是根据应用程序控制器代码来决定是否采用共享单例,还是就每个请求生成新的控制器实例。

1. 无字段的控制器 - 处理为单例

public class HelloController {
    
    @GetAction("/hello")
    public String sayHello() {
        return "Hello world!";
    }    
            
}

上面的控制器没有任何字段,因此对于任何发往 /hello 的请求,只会有一个 HelloController 的实例来响应。

2. 有字段的控制器 - 每个请求生成新的实例

public class LoggedInHelloController {

    @LoginUser User me;
    
    @GetAction("/hi")
    public String sayHi() {
        return "Hi from " + me.getFullName();
    }    

}

LoggedInHelloController 控制器有一个字段 User me,因此 ActFramework 认定这个控制器是有状态的,所以会对每个请求生成新的控制器实例。

3. 所有字段为无状态的控制器 - 处理为单例

@Entity("user")
public class User {...}

@Stateless
public class UserDao extends EbeanDao<User> {...}

@UrlContext("/users")
public class UserController {
    @Inject
    private UserDao userDao;
    
    @PostAction
    public User create(User user) {return userDao.save(user);}

    @GetAction
    public Iterable<User> list() {return userDao.findAll();}

    ...
}

上面的 UserDao 类被标注为 @Stateless,因此虽然 UserController 类中有 UserDao userDao 的字段,ActFramework 依然认定 UserController 是无状态的,所以所有请求响应会共享一个 UserController 实例

在类上标注 @Stateless 的方法非常简便好用,但当控制器中需要注入来自三方库的无状态对象,应用程序开发人员没有办法改变其代码,因此只能在使用的地方标注 @Stateless

public class SuperHelloController {
    @Stateless
    @Inject
    private HelloHelper helper;
    
    @GetAction("/superHello")
    public String superHello() {
        return helper.hello();
    }
}

SuperHelloController 中有一个 HelloHelper helper 字段,假设 HelloHelper 类来自三方库,而我们确信这个类和请求无关,因此标注该字段为 @Stateless,这样 ActFramework 会认定 SuperHelloController 为无状态的,所有请求共享一个 SuperHelloController 实例。

4. 总结

ActFramework 依据控制器的字段状态来判定是否对控制器做单例,或者多实例处理

  • 当控制器无字段时,控制器处理为单例
  • 当控制器有字段时:
    • 如果所有字段均有标注 @Stateless 或字段类型上有 @Stateless 标注,则处理为单例
    • 如果存在非 @Stateless 的字段,则处理为多实例

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java思维导图

自己手写一个 SpringMVC 框架

前端框架很多,但没有一个框架称霸,后端框架现在Spring已经完成大一统.所以学习Spring是Java程序员的必修课. Spring 框架对于 Java 后端...

3866
来自专栏Java技术栈

从 0 开始手写一个 Spring MVC 框架,向高手进阶!

Spring框架对于Java后端程序员来说再熟悉不过了,以前只知道它用的反射实现的,但了解之后才知道有很多巧妙的设计在里面。如果不看Spring的源码,你将会失...

782
来自专栏me的随笔

抽象类 VS 接口

接口和抽象类是面向对象编程(OOP, Object Oriented programming)中两个绕不开的概念,二者相似而又有所不同。接下来,我们来了解二者的...

833
来自专栏JAVA高级架构

自己手写一个 SpringMVC 框架

前端框架很多,但没有一个框架称霸,后端框架现在Spring已经完成大一统.所以学习Spring是Java程序员的必修课. Spring 框架对于 Java 后...

32610
来自专栏java思维导图

Spring思维导图,让Spring不再难懂(mvc篇)

在前面 生活就像海洋,只有意志坚强的人才能到达彼岸。已经很久没有发文章了呀,想必大家都挂念我了,哈哈。温故而知新,今天一起来复习一下spring mvc的内容吧...

3503
来自专栏Java架构沉思录

聊聊Java动态代理(下)

前言 在之前的文章《聊聊Java动态代理(上)》中,笔者为大家介绍了Java原生的动态代理,并指出Java原生的动态代理有一个缺点就是被代理类必须显示地实现某个...

2899
来自专栏不想当开发的产品不是好测试

优化testng报告

背景 搞过testng的同学都知道,testng自带的报告非常丑,而且有些字段的展示很不人性化,所以需要优化下报告 ? 解决方案 尝试过一下开源的jar包,如R...

1997
来自专栏Web项目聚集地

自己手写一个Spring MVC框架

Spring框架对于Java后端程序员来说再熟悉不过了,以前只知道它用的反射实现的,但了解之后才知道有很多巧妙的设计在里面。

1083
来自专栏Java架构沉思录

聊聊Java动态代理(上)

前言 在之前的文章《聊聊设计模式之代理模式》中,笔者为大家介绍了代理模式,在这里简单回顾一下。代理模式的作用是提供一个代理来控制对一个对象的访问,因此我们可以...

34413
来自专栏代码散人

Kotlin和Swift横向对比

kotlin面世已经有不短的时间了,从安卓宣布kotin为安卓官方开发语言开始,kotlin的热度开始猛涨,作为一个从swift1.0开始写iOS程序的开发者自...

582

扫码关注云+社区