CDI技术第二步,范围注解
CDI管理的Bean,有范围区别的。
主要有以下范围
1 request范围,也就是对于每个web请求,会新建一个对象。注解使用@RequestScoped
2 session范围,意思是对于每个web会话,会新建一个对象。注解使用@SessionScoped
3 application范围,对于每个web应用,维护一个对象注解使用@ApplicationScoped
4 conversation范围,对于一个持续的会话,维护一个对象。服务器可以用代码来控制conversation何时结束。注解使用@ConversationScoped
5 normal范围,也就是说一个正常范围。注解使用@NormalScoped
6 dependent范围,比request范围有更多的对象,也就是需要就新建一个。
首先来实验一下。注解使用@Dependent
7 无范围,其实和dependency范围一致,注解使用@Scoped
为了证明是每次请求都会new新的对象出来,我们写几段代码试试就知道了。注解使用@RequestScoped
首先接口
package com.rschy.cdiscope.service; public interface RequestService {}
其次实现类
package com.rschy.cdiscope.bean; import javax.enterprise.context.RequestScoped; import com.rschy.cdiscope.service.RequestService; @RequestScoped public class RequestServiceBean implements RequestService {}
然后在servlet中试验一番
package com.rschy.cdiscope.web; import java.io.IOException; import javax.inject.Inject; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.rschy.cdiscope.service.RequestService; @WebServlet("/request.html") public class RequestServlet extends HttpServlet {
private static final long serialVersionUID = 1L; private @Inject RequestService requestService;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().append("The Service toString:").append(requestService.toString()); } }
可以看到两次内存地址是不一样的。
那么试试session Scoped。
我就不贴那么冗长的代码了。
只复制一个带注解的实现类。必须注意的一点就是session范围的Bean必须序列化。
同样需要序列化的还有对话范围(conversation scope),application范围的bean。如果不序列化,是会报错的。
package com.rschy.cdiscope.bean; import java.io.Serializable; import javax.enterprise.context.SessionScoped; import com.rschy.cdiscope.service.SessionService; @SessionScoped() public class SessionServiceBean implements SessionService,Serializable { private static final long serialVersionUID = 1L; }
我们写个新的servlet试一试就可以了。
那么结果就是页面重复刷新,都是以下这个结果。
但是我换个浏览器就不一样了。
下面我们再试试应用范围的。
package com.rschy.cdiscope.bean; import java.io.Serializable; import javax.enterprise.context.ApplicationScoped; import com.rschy.cdiscope.service.ApplicationService; @ApplicationScoped() public class ApplicationServiceBean implements ApplicationService,Serializable { private static final long serialVersionUID = 1L; }
看看结果,可以看到无论换什么浏览器都是同一个对象。
接下来就是我们的难点了,交流范围。就是让程序主动去结束交流。
对于对话范围,如果不人为地去定义边界,它默认是等于请求范围的,也就是request scope。
这个conversation scope的问题,我会写下一篇博文来仔细解释。