谈一谈 Bean的作用域

    Hasor 在管理 Bean 的时候支持作用域。一个典型的作用域应用场景就是“单例”,单例作用域的表现是整个应用程序中只保存一份。

    另外一个作用域的例子是用户登录网站之后web应用程序通过 session 保持会话。当然你可以根据应用业务实际场景来决定作用域的用处。

    在例如,在一个应用平台的项目中。每个应用都是一个独立的包,每个应用都有自己的运行信息。这些运行信息彼此隔离在不同的应用中,这种场景就很适合使用作用域。

    好了,有关作用域究竟是个什么东西,已经说的很明白了。现在我们回到最初的问题。Hasor 的 Bean 如何实现不同作用域之间的隔离。

    在 Hasor 中实现中完成作用域需要实现 Scope 接口,这个接口只有一个 scope 方法。下面就以 HttpSession 为作用域范围实现 Scope 接口的例子:

public class SessionScope implements Scope{
    private static final ThreadLocal<HttpSession> session = new ThreadLocal<HttpSession>();

    public <T> Provider<T> scope(Object key, Provider<T> provider) {
        HttpSession httpSession = session.get();
        if (httpSession == null) {
            return provider;
        }
        String keyStr = "session_scope_" + key.toString();
        Object attribute = httpSession.getAttribute(keyStr);
        Provider<T> finalProvider = provider;
        if (attribute == null) {
            httpSession.setAttribute(keyStr, provider);
        } else {
            finalProvider = (Provider<T>) httpSession.getAttribute(keyStr);
        }
        return finalProvider;
    }
}

     在例子中为了避免保存到 Session 中的 Bean 和本身 Session 中的数据 key 出现冲突,我们特意加了一个前缀用于区分。

    现在作用域的功能是有了,但是我们的 HttpSession 对象的还没有做初始化。这次我们来实现 Filter 接口,在每次 request 请求到来的时候把 Session 都更新到 ThreadLocal 中。在访问结束之后再把 ThreadLocal 清理掉。

    下面来看改造了之后的 Scope 代码:

public class SessionScope implements Scope, Filter {
    private static final ThreadLocal<HttpSession> session = new ThreadLocal<HttpSession>();

    public void init(FilterConfig filterConfig) throws ServletException { /**/ }
    public void destroy() { /**/ }
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        try {
            if (session.get() != null) {
                session.remove();
            }
            session.set(((HttpServletRequest) request).getSession(true));
            chain.doFilter(request, response);
        } finally {
            if (session.get() != null) {
                session.remove();
            }
        }
    }

    public <T> Provider<T> scope(Object key, Provider<T> provider) {
        HttpSession httpSession = session.get();
        if (httpSession == null) {
            return provider;
        }
        String keyStr = "session_scope_" + key.toString();
        Object attribute = httpSession.getAttribute(keyStr);
        Provider<T> finalProvider = provider;
        if (attribute == null) {
            httpSession.setAttribute(keyStr, provider);
        } else {
            finalProvider = (Provider<T>) httpSession.getAttribute(keyStr);
        }
        return finalProvider;
    }
}

    从上面例子代码中看到进入 filter 时做了 Session 的初始化将其保存到 ThreadLocal ,离开之后又把 ThreadLocal 清理掉。

    最后我们在 Hasor 初始化的时候把 Scope 配置到 Hasor 中。

public class StartModule extends WebModule {
    public void loadModule(WebApiBinder apiBinder) throws Throwable {
        ...
        SessionScope scope = new SessionScope();
        apiBinder.filter("/*").through(0, scope);
        apiBinder.registerScope("session", scope);
        ...
    }
}

    接下来使用这个 Scope:

apiBinder.bindType(UserInfo.class).toScope(new SessionScope());
//or
apiBinder.bindType(UserInfo.class).toScope("session");

 

转载于:https://my.oschina.net/ta8210/blog/754000

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值