• Compartilhar
  • ?
  • Perfis ▼
  • Comunidades ▼
  • Aplicativos ▼

Blogs

  • Meus Blogs
  • Blogs Públicos
  • Minhas Atualizações

한국 developerWorks 로컬 콘텐츠

  • Efetue login para participar
9e635b49-09e9-4c23-8999-a4d461aeace2 Blog

▼ Marcações

▼ Entradas Semelhantes

How to list row-orgn...

Blog: Thoughts from...
AjayMPatil 31000030FM
Atualizado
0 pessoas curtiram istoCurtir 0
Sem ComentáriosComentários 0

DB2 Tech Talk: Insid...

Blog: SQL Tips for ...
SergeRielau 120000D76F
Atualizado
0 pessoas curtiram istoCurtir 0
Sem ComentáriosComentários 0

DB2 calling REORG co...

Blog: Hazem Saleh
Hazem Saleh (IBM) 2700027XCV
Atualizado
0 pessoas curtiram istoCurtir 0
Sem ComentáriosComentários 0

DB2 10: Generated co...

Blog: SQL Tips for ...
SergeRielau 120000D76F
Atualizado
0 pessoas curtiram istoCurtir 0
ComentáriosComentários 5

Scoping rules in DB...

Blog: SQL Tips for ...
SergeRielau 120000D76F
Atualizado
1 pessoa curtiu istoCurtir 1
ComentáriosComentários 4

▼ Archive

  • fevereiro de 2012
  • janeiro de 2012
  • outubro de 2011
  • setembro de 2011
  • agosto de 2011
  • julho de 2011
  • março de 2011
  • fevereiro de 2011
  • janeiro de 2011
  • dezembro de 2010
  • novembro de 2010
  • setembro de 2010
  • agosto de 2010
  • julho de 2010

▼ Autores do Blog

한국 developerWorks 로컬 콘텐츠

자바 EE 6에서 의존성 주입

dWkorea 270002XP5U | | Marcações:  column | 4.467 Visualizações

이창신이창신 iasandcb@gmail.com, http://iasandcb.pe.kr

티맥스소프트 JEUS팀, 엔씨소프트 오픈마루 스튜디오를 거쳐 현재 인디 개발자로 활동하고 있다. 

2009년 12월 8일


어느덧 이 컬럼을 시작한 지도 1년이 다 되어간다. 두 달에 한번 쓰는 것이라 부담이 없으리라 생각했는데, 그렇게 만만치만은 않은 것임을 새삼 느낀다.

지난 10월에 쓴 글에서 자바 EE 6 완결판을 소개하기를 고대한다고 했는데 실제로 스펙이 최종 승인됐다. 자바 EE 6 스펙 리드인 Roberto Chinnicij이 자기 블로그 포스트에서 이 기쁜(?) 소식을 타전했다. 급하게나마 자바 EE 6 API 문서 전체는http://javadoc.glassfish.org/javaee6/apidoc/에서 확인할 수 있다. 최종 스펙 문서와 참조 구현체인 글래스피시(GlassFish) V3 최종판(그리고 이를 지원하는 넷빈즈(NetBeans) 6.8 최종판)은 12월 10일 출시될 예정이다.

따라서 최종판 자바 EE 6를 완벽히 누리는 것은 다음 기회로 미루고, 이번에는 자바 EE 6의 일정에까지 영향을 준 의존성 주입(이하 DI) 기능에 대해 알아보자.

새 DI 맛보기

본격적으로 들어가기에 앞서, 넷빈즈 6.8(2009년 12월 3일 현재 RC1)을 http://netbeans.org/community/releases/68/에서 받아 설치해둔다(이때 함께 설치되는 글래스피시는 빌드 73이다).

애초 자바 EE 6의 DI는 JSR 299 Web Beans라는 이름으로 표준화가 진행되다가, Java Contexts and Dependency Injection for Java EE(이 이름이 너무 길어 대신 CDI라고 줄여 쓴다)라는 좀 더 구체적인 이름으로 바뀌었다. 하지만 JSR 299는 여전히 Web Beans라는 이름으로 자주 불린다(일종의 애칭처럼 되어버렸다). 해당 스펙 리드인 Gavin King(하이버네이트(Hibernate) 창시자로 유명하며, 최근 방한해 한국 개발자들에게도 더욱 친숙해졌다)이 JBoss에서 구현하는 참조 구현체 이름도 처음에는 Web Beans였다가 최근 스펙 이름이 바뀌면서 혼동을 피하기 위해 Weld로 바꾸었다(http://seamframework.org/Weld/WeldOverview참조).

이미 스프링 같은 DI 프레임워크가 많이 소개되어 DI 자체에 대한 설명은 차치하고, 대신 CDI를 어떻게 사용하는지 간단한 예제와 함께 살펴보려 한다. https://glassfish-samples.dev.java.net/에는 글래스피시를 기반으로 다양한 예제를 제공하는데, CDI에 대한 예제도 들어 있어서 http://weblogs.java.net/blog/rogerk/archive/2009/09/09/context-and-dependency-injection-jsr-299-and-servlets에 간략히 소개되기도 했다.

우리가 다룰 예제는 정확히 https://glassfish-samples.dev.java.net/source/browse/glassfish-samples/ws/javaee6/webbeans/webbeans-servlet/ 이하에서 볼 수 있지만, 코드를 편하게 보고 실제 실행하려면https://glassfish-samples.dev.java.net/source/browse/glassfish-samples/ 페이지에 나온 안내에 따라 CVS로 체크아웃해 받아보는 것이 편하다. 반드시 glassfish-samples라는 모듈 전체를 받기를 권하며, 그 밑으로 ws/javaee6/webbeans/webbeans-servlet 디렉터리를 넷빈즈에서 Open Project로 열면 간단히 실행까지 해볼 수 있다.

webbeans-servlet 실행 결과 화면
그림 1. webbeans-servlet 실행 결과 화면

위 화면에서 User Name과 Password는 아무것이나 입력해도 상관 없다. 단 입력하지 않으면 로그인이 안된다. 그러면 위와 같이 돌아가는 웹 애플리케이션을 바닥부터 만들어 보자.

우선, New Project -> Java Web -> Web Application을 선택하여 웹 애플리케이션 프로젝트를 생성한다. 프로젝트 이름(Project Name)은 webbeans-test로 하여 앞서 열어본 프로젝트의 이름을 피한다. Next 버튼을 누르면 Java EE Version을 선택하게 되는데 Java EE 6 Web임을 확인하고 넘어가면 된다.

프로젝트 생성을 마쳤으니 본격적으로 코드 작성에 돌입하자. 먼저 DI를 할 대상들로, 사용자 인증 정보를 나타내는 Credentials 클래스와 인증 처리를 하는 Login 클래스를 만드는데, 프로젝트 홈 밑의 Source Packages 밑으로 New > Java Class를 선택하여 아래와 같이 짠다(패키지를 webbeansservlet으로 하는 것도 잊지 말자).

Listing 1. Credentials.java
package webbeansservlet; 
import java.io.Serializable; 
import javax.enterprise.context.RequestScoped; 
import javax.enterprise.inject.Default; 
import javax.inject.Named; 
@RequestScoped 
public class Credentials implements Serializable { 
    private String username = null; 
    private String password = null; 
    public String getUsername() {  
        return username;  
    } 
    public void setUsername(String username) {  
        this.username = username;  
    } 
    public String getPassword() {  
        return password;  
    } 
    public void setPassword(String password) {  
        this.password = password;  
    } 
} 

Credentials 클래스는 일반적인 자바 클래스(POJO) 같지만 @RequestScoped라는 CDI 어노테이션이 붙어 CDI의 범위를 한정한다. 또한 Serializable을 구현하여 보존성을 확보한다.

Listing 2. Login.java
package webbeansservlet; 
import java.io.Serializable; 
import javax.enterprise.context.SessionScoped; 
import javax.inject.Inject; 
@SessionScoped 
public class Login implements Serializable { 
    @Inject Credentials credentials; 
    private boolean loggedIn = false; 
    /** 
     * This is where you could potentially access a database. 
     */ 
    public void login() { 
        if ((credentials.getUsername() != null && 
            credentials.getUsername().trim().length() > 0) && 
            (credentials.getPassword() != null && 
            credentials.getPassword().trim().length() > 0)) { 
            loggedIn = true; 
        } 
    } 
    public boolean isLoggedIn() { 
        return loggedIn; 
    } 
} 

Login 클래스는 Credentials와는 달리 @SessionScoped로 세션 범위임을 선언하는데, 그 안에 @Inject 어노테이션을 통해 credentials 필드에 DI를 하고 있다. 그러면 이제 Credentials와 Login을 웹 애플리케이션 수준에서 사용할 수 있도록 LoginServlet을 작성해보자.

프로젝트 홈 밑의 Source Packages 밑으로 New > Servlet을 선택하여 패키지 이름으로 webbeansservlet과 클래스 이름으로 LoginServlet을 입력한 다음, Servlet Name과 URL Pattern(s), Add information to deployment descriptor (web.xml) 설정은 주어진 대로 하고 넘어간다(이렇게 하면 web.xml이 생성되지 않고도 서블릿을 실행할 수 있다). 아래는 LoginServlet 코드다.

Listing 3. LoginServlet
package webbeansservlet; 
import java.io.IOException; 
import java.io.PrintWriter; 
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; 
@WebServlet(name="LoginServlet", urlPatterns={"/LoginServlet"}) 
public class LoginServlet extends HttpServlet { 
    @Inject Credentials credentials; 
    @Inject Login login; 
    protected void processRequest(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException { 
        response.setContentType(&amp;amp;quot;text/html;charset=UTF-8&amp;amp;quot<img src="https://www.ibm.com/developerworks/community/blogs/images/smileys/wink.gif" class="smiley" alt=";)" title=";)" />; 
        PrintWriter out = response.getWriter(); 
        credentials.setUsername(request.getParameter(&amp;amp;quot;username&amp;amp;quot<img src="https://www.ibm.com/developerworks/community/blogs/images/smileys/wink.gif" class="smiley" alt=";)" title=";)" />); 
        credentials.setPassword(request.getParameter(&amp;amp;quot;password&amp;amp;quot<img src="https://www.ibm.com/developerworks/community/blogs/images/smileys/wink.gif" class="smiley" alt=";)" title=";)" />); 
        login.login(); 
        try { 
            if (login.isLoggedIn()) { 
                out.println(&amp;amp;quot;Successfully Logged In As: &amp;amp;quot; + credentials.getUsername()); 
            } else { 
                out.println(&amp;amp;quot;Login Failed: Check username and/or password.&amp;amp;quot<img src="https://www.ibm.com/developerworks/community/blogs/images/smileys/wink.gif" class="smiley" alt=";)" title=";)" />; 
            } 
        } finally {  
            out.close(); 
        } 
    }  
    @Override 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException { 
        processRequest(request, response); 
    }  
    @Override 
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException { 
        processRequest(request, response); 
    } 
}

이 서블릿의 credentials와 login 필드 모두 DI로 형성되는데, processRequest 안을 보면 요청으로 들어온 정보로 credentials를 채운다. 다음으로 login.login() 메서드로 로그인 처리를 호출하고 나서 login.isLoggedIn() 메서드로 로그인 상태에 따라 메시지를 반환한다.

여기서 기존 코딩 방식과 다른 점은, credentials를 채운 다음 login에 따로 넣어줄 필요가 없다는 점이다. 즉 credentials의 username과 password를 설정한 다음 login.login() 메서드를 부르는 시점에 이미 login의 credentials 필드도 같은 상태가 되어 있다. 특히 credentials가 요청 범위(Request Scope)이므로, processRequest 안에서는 똑같은 값으로 유지될 것이며, login은 세션 범위이므로 요청을 넘어 세션에 걸쳐 유지될 것이다. 이 서블릿을 부르는 HTML 페이지는 다음과 같다.

Listing 4. index.jsp

&amp;amp;lt;%@page contentType=&amp;amp;quot;text/html&amp;amp;quot; pageEncoding=&amp;amp;quot;UTF-8&amp;amp;quot;%&amp;amp;gt; 
&amp;amp;lt;!DOCTYPE HTML PUBLIC &amp;amp;quot;-//W3C//DTD HTML 4.01 Transitional//EN&amp;amp;quot; 
   &amp;amp;quot;http://www.w3.org/TR/html4/loose.dtd&amp;amp;quot;&amp;amp;gt; 
&amp;amp;lt;html&amp;amp;gt; 
    &amp;amp;lt;head&amp;amp;gt; 
        &amp;amp;lt;meta http-equiv=&amp;amp;quot;Content-Type&amp;amp;quot; content=&amp;amp;quot;text/html; charset=UTF-8&amp;amp;quot;&amp;amp;gt; 
        &amp;amp;lt;title&amp;amp;gt;Web Beans Servlet Injection&amp;amp;lt;/title&amp;amp;gt; 
        &amp;amp;lt;script type=&amp;amp;quot;text/javascript&amp;amp;quot; src=&amp;amp;quot;ajax.js&amp;amp;quot;&amp;amp;gt; 
        &amp;amp;lt;/script&amp;amp;gt; 
    &amp;amp;lt;/head&amp;amp;gt; 
    &amp;amp;lt;body&amp;amp;gt; 
        &amp;amp;lt;form name=&amp;amp;quot;myForm&amp;amp;quot; method=&amp;amp;quot;POST&amp;amp;quot; action=&amp;amp;quot;LoginServlet&amp;amp;quot;&amp;amp;gt; 
            &amp;amp;lt;table class=&amp;amp;quot;title-panel&amp;amp;quot;&amp;amp;gt; 
                &amp;amp;lt;tbody&amp;amp;gt; 
                    &amp;amp;lt;tr&amp;amp;gt; 
                        &amp;amp;lt;td&amp;amp;gt;&amp;amp;lt;span class=&amp;amp;quot;title-panel-text&amp;amp;quot;&amp;amp;gt;Login Servlet&amp;amp;lt;/span&amp;amp;gt;&amp;amp;lt;/td&amp;amp;gt; 
                    &amp;amp;lt;/tr&amp;amp;gt; 
                    &amp;amp;lt;tr&amp;amp;gt; 
                        &amp;amp;lt;td&amp;amp;gt;&amp;amp;lt;span class=&amp;amp;quot;title-panel-subtext&amp;amp;quot;&amp;amp;gt;Powered By Servlet 3.0 and Web Beans&amp;amp;lt;/span&amp;amp;gt;&amp;amp;lt;/td&amp;amp;gt; 
                    &amp;amp;lt;/tr&amp;amp;gt; 
                &amp;amp;lt;/tbody&amp;amp;gt; 
            &amp;amp;lt;/table&amp;amp;gt; 
            &amp;amp;lt;table height=&amp;amp;quot;30&amp;amp;quot; style=&amp;amp;quot;font-size: 16px&amp;amp;quot;&amp;amp;gt; 
              &amp;amp;lt;tr&amp;amp;gt; 
                &amp;amp;lt;td&amp;amp;gt;Enter any value for user name and password.&amp;amp;lt;/td&amp;amp;gt; 
              &amp;amp;lt;/tr&amp;amp;gt; 
            &amp;amp;lt;/table&amp;amp;gt; 
            &amp;amp;lt;table style=&amp;amp;quot;font-size: 16px&amp;amp;quot;&amp;amp;gt; 
              &amp;amp;lt;tr&amp;amp;gt; 
                &amp;amp;lt;td style=&amp;amp;quot;color:red&amp;amp;quot;&amp;amp;gt;*&amp;amp;lt;/td&amp;amp;gt; 
                &amp;amp;lt;td&amp;amp;gt;Denotes required entry.&amp;amp;lt;/td&amp;amp;gt; 
              &amp;amp;lt;/tr&amp;amp;gt; 
            &amp;amp;lt;/table&amp;amp;gt; 
            &amp;amp;lt;table height=&amp;amp;quot;30&amp;amp;quot;&amp;amp;gt; 
            &amp;amp;lt;table border=&amp;amp;quot;1&amp;amp;quot; style=&amp;amp;quot;font-size: 18px&amp;amp;quot;&amp;amp;gt; 
              &amp;amp;lt;tr&amp;amp;gt; 
                &amp;amp;lt;td&amp;amp;gt;User Name:&amp;amp;lt;/td&amp;amp;gt; 
                &amp;amp;lt;td&amp;amp;gt;&amp;amp;lt;input type=&amp;amp;quot;text&amp;amp;quot; name=&amp;amp;quot;username&amp;amp;quot; id=&amp;amp;quot;username&amp;amp;quot; /&amp;amp;gt;&amp;amp;lt;/td&amp;amp;gt; 
                &amp;amp;lt;td style=&amp;amp;quot;color:red&amp;amp;quot;&amp;amp;gt;*&amp;amp;lt;/td&amp;amp;gt; 
              &amp;amp;lt;/tr&amp;amp;gt; 
              &amp;amp;lt;tr&amp;amp;gt; 
                &amp;amp;lt;td&amp;amp;gt;Password:&amp;amp;lt;/td&amp;amp;gt; 
                &amp;amp;lt;td&amp;amp;gt;&amp;amp;lt;input type=&amp;amp;quot;password&amp;amp;quot; name=&amp;amp;quot;password&amp;amp;quot; id=&amp;amp;quot;password&amp;amp;quot; /&amp;amp;gt;&amp;amp;lt;/td&amp;amp;gt; 
                &amp;amp;lt;td style=&amp;amp;quot;color:red&amp;amp;quot;&amp;amp;gt;*&amp;amp;lt;/td&amp;amp;gt; 
              &amp;amp;lt;/tr&amp;amp;gt; 
            &amp;amp;lt;/table&amp;amp;gt; 
            &amp;amp;lt;table border=&amp;amp;quot;1&amp;amp;quot;&amp;amp;gt; 
              &amp;amp;lt;tr&amp;amp;gt; 
                &amp;amp;lt;td colspan=&amp;amp;quot;2&amp;amp;quot;&amp;amp;gt;&amp;amp;lt;input type=&amp;amp;quot;button&amp;amp;quot; value=&amp;amp;quot;Submit&amp;amp;quot;  onclick=&amp;amp;quot;ajaxFunction();&amp;amp;quot; /&amp;amp;gt;&amp;amp;lt;/td&amp;amp;gt; 
                &amp;amp;lt;td colspan=&amp;amp;quot;2&amp;amp;quot;&amp;amp;gt;&amp;amp;lt;input type=&amp;amp;quot;button&amp;amp;quot; value=&amp;amp;quot;Reset&amp;amp;quot;  onclick=&amp;amp;quot;resetFunction();&amp;amp;quot; /&amp;amp;gt;&amp;amp;lt;/td&amp;amp;gt; 
              &amp;amp;lt;/tr&amp;amp;gt;  
            &amp;amp;lt;/table&amp;amp;gt; 
            &amp;amp;lt;/table&amp;amp;gt; 
            &amp;amp;lt;table height=&amp;amp;quot;20&amp;amp;quot;&amp;amp;gt; 
              &amp;amp;lt;tr&amp;amp;gt; 
                &amp;amp;lt;td&amp;amp;gt;&amp;amp;lt;div id=&amp;amp;quot;message&amp;amp;quot; style=&amp;amp;quot;color:red;font-size: 14px&amp;amp;quot;&amp;amp;gt;&amp;amp;lt;/td&amp;amp;gt; 
              &amp;amp;lt;/tr&amp;amp;gt; 
            &amp;amp;lt;/table&amp;amp;gt; 
         &amp;amp;lt;/form&amp;amp;gt; 
    &amp;amp;lt;/body&amp;amp;gt; 
&amp;amp;lt;/html&amp;amp;gt; 

이 파일은 프로젝트 루트의 Web Pages 밀에 이미 생성되어 있으므로 위와 같이 바꾸기만 하면 된다. 위 페이지는 Ajax를 사용하는데 자바스크립트 코드는 ajax.js라는 파일로 따로 두었다.

Listing 5. ajax.js
        function getXMLObject()  { 
            var xmlHttp = false; 
            try { 
                xmlHttp = new ActiveXObject(&amp;amp;quot;Msxml2.XMLHTTP&amp;amp;quot<img src="https://www.ibm.com/developerworks/community/blogs/images/smileys/wink.gif" class="smiley" alt=";)" title=";)" />  // For Old Microsoft Browsers 
            } catch (e) { 
                try { 
                    xmlHttp = new ActiveXObject(&amp;amp;quot;Microsoft.XMLHTTP&amp;amp;quot<img src="https://www.ibm.com/developerworks/community/blogs/images/smileys/wink.gif" class="smiley" alt=";)" title=";)" />  // For Microsoft IE 6.0+ 
                } catch (e2) { 
                    xmlHttp = false   // No Browser accepts the XMLHTTP Object then false 
                } 
            } 
            if (!xmlHttp &amp;amp;amp;&amp;amp;amp; typeof XMLHttpRequest != 'undefined') { 
                xmlHttp = new XMLHttpRequest();        //For Mozilla, Opera Browsers 
            } 
            return xmlHttp;  // Mandatory Statement returning the ajax object created 
        } 
        var xmlhttp = new getXMLObject(); 
        function ajaxFunction() { 
            if(xmlhttp) { 
                var username = document.getElementById(&amp;amp;quot;username&amp;amp;quot<img src="https://www.ibm.com/developerworks/community/blogs/images/smileys/wink.gif" class="smiley" alt=";)" title=";)" />; 
                var password = document.getElementById(&amp;amp;quot;password&amp;amp;quot<img src="https://www.ibm.com/developerworks/community/blogs/images/smileys/wink.gif" class="smiley" alt=";)" title=";)" />; 
                xmlhttp.open(&amp;amp;quot;POST&amp;amp;quot;,&amp;amp;quot;LoginServlet&amp;amp;quot;,true); //getname will be the servlet name 
                xmlhttp.onreadystatechange  = handleServerResponse; 
                xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 
                xmlhttp.send(&amp;amp;quot;username=&amp;amp;quot; + username.value + &amp;amp;quot;&amp;amp;amp;password=&amp;amp;quot; + password.value); 
            } 
        } 
        function handleServerResponse() { 
            if (xmlhttp.readyState == 4) { 
                if(xmlhttp.status == 200) { 
                    document.getElementById(&amp;amp;quot;message&amp;amp;quot<img src="https://www.ibm.com/developerworks/community/blogs/images/smileys/wink.gif" class="smiley" alt=";)" title=";)" />.innerHTML=xmlhttp.responseText;  
                } else { 
                    alert(&amp;amp;quot;Error during AJAX call. Please try again&amp;amp;quot<img src="https://www.ibm.com/developerworks/community/blogs/images/smileys/wink.gif" class="smiley" alt=";)" title=";)" />; 
                } 
            } 
        } 
        function resetFunction() { 
            document.getElementById(&amp;amp;quot;username&amp;amp;quot<img src="https://www.ibm.com/developerworks/community/blogs/images/smileys/wink.gif" class="smiley" alt=";)" title=";)" />.value=&amp;amp;quot;&amp;amp;quot;; 
            document.getElementById(&amp;amp;quot;password&amp;amp;quot<img src="https://www.ibm.com/developerworks/community/blogs/images/smileys/wink.gif" class="smiley" alt=";)" title=";)" />.value=&amp;amp;quot;&amp;amp;quot;; 
            document.getElementById(&amp;amp;quot;message&amp;amp;quot<img src="https://www.ibm.com/developerworks/community/blogs/images/smileys/wink.gif" class="smiley" alt=";)" title=";)" />.innerHTML=&amp;amp;quot;&amp;amp;quot;; 
        } 
 

이 파일을 프로젝트 루트의 Web Pages에서 New > Web > JavaScript File을 선택하여 생성하면 된다. 그런데 이와 같이 다 된 듯하여 실행해 보면 정작 DI가 되질 않는다. 결론부터 말하면, WEB-INF 프로젝트 루트의 Web Pages > WEB-INF 디렉터리 밑에 beans.xml이라는 파일을 다음과 같은 내용으로 작성해야 한다.

Listing 6. beans.xml

&amp;amp;lt;?xml version=&amp;amp;quot;1.0&amp;amp;quot; encoding=&amp;amp;quot;UTF-8&amp;amp;quot;?&amp;amp;gt; 
&amp;amp;lt;beans/&amp;amp;gt;  

이렇게 하고 나서 빌드와 배포를 한 다음 http://localhost:8080/webbeans-test/를 브라우저로 열면 맨 앞에서 본 것과 비슷한(똑같지는 않다) 화면과 처리가 된다.


좀 더 범용적인 DI로 돌아오다

앞서 소개한 예제의 DI 관련 코드를 유심히 봤다면, 어노테이션에 두 종류가 있음을 알 수 있다. 하나는 javax.inject 패키지 계열(@Inject)이고, 또 하나는 javax.enterprise.inject 패키지 계열(@RequestScoped, @SessionScoped)인데, 바로 이것이 자바 EE 6 스펙 제정의 대단원의 막을 장식한 JSR 330 Dependency Injection for Java와 JSR 299 CDI의 결합이다. JSR 299는 JBoss의 Gavin King이 이끄는 심(Seam) 프레임워크의 산물이라면, JSR 330은 스프링(Spring)의 Rod Johnson과 Guice(구글의 DI 프레임워크)의 구글이 좀 더 범용적인 DI 표준을 제시한 것이다. 자바 EE와 자바 SE가 DI에 있어 중복을 피한 것은 자바 EE 6가 다소 늦어진 것에 대한 충분한 보상이 되리라 믿는다. 
Efetue login para acessar este recurso
  • Incluir um Comentário
  • Mais Ações v
Notificar Outras Pessoas
  • Incluir um Comentário
  • Editar
  • Mais Ações v
  • Colocar esta Entrada em Quarentena
Notificar Outras Pessoas
notification_ex

Enviar Notificação por Email

Colocar esta entrada em quarentena

deleteEntry
duplicateEntry

Marcar como Duplicata

  • Entrada Anterior
  • Principal
  • Próxima Entrada
Feed para Entradas de Blog ▼ | Feed para Comentários de Blog ▼ | Feed para Comentários desta Entrada ▼