Java

CDI를 이용한 Java 개발

gregorio 2018. 2. 13. 15:25

Spring Framework에서 다양한 Annotation을 지원해주기 때문에 프로그램 개발 시 필요한 Bean을 찾아서 사용하면 되는 강력한 기능을 제공하고 있다.


그러나 Spring Framework를 사용하지 않는 일반 POJO 프로그램에서 Annotation을 이용하여 Bean을 가져 올 수 있는 방법을 찾던 중에  JBOSS에서 제공하는 CDI(Context and Dependency Injection)를 적용할 수 있도록 개발했던 내용이다.


먼저 CDI를 사용하기 위해서는 jar 프로젝트에서는 /src/main/resources/META-INF 폴더에 beans.xml을 생성해야 한다.


■ beans.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"

       bean-discovery-mode="all">

       

</beans>


Bean으로 사용하기 위한 Class를 다음과 같이 생성한다.


■LowerCaseTextProcssor.java

 import javax.inject.Named;


@Named("lowerCase")

public class LowerCaseTextProcessor implements TextProcessor{


public String processText(String text) {

return text.toLowerCase();

}

}

LowerCaseTextProcess의 Class에 @Named Annotation을 이용하여 bean 이름을 설정한다.

여기서는 bean 이름을 lowerCase로 설정하였다.



프로젝트에 여러개의 Bean이 설정될 수 있기 때문에서 bean이름으로 해당 Class를 Return하는 공통 Class를 작성하여 Bean을 가져 올 수 있게 한다.


■BeanUtil.java

import java.util.Iterator;

import java.util.Set;


import javax.annotation.PreDestroy;

import javax.enterprise.inject.spi.Bean;


import org.jboss.weld.environment.se.Weld;

import org.jboss.weld.environment.se.WeldContainer;


public class BeanUtil {


private static WeldContainer container = null;

private static Weld weld = null;

private static Object sync = new Object();

/**

*<pre>

* Return bean class

*</pre>

* @param beanName

* @return

* @throws Exception

*/

@SuppressWarnings("unchecked")

public static <T> T getBean(String beanName) throws Exception {

init();

Set<Bean<?>> beans = container.getBeanManager().getBeans(beanName);

    Class<?> clazz = null;

//    beans = CDI.current().getBeanManager().getBeans(beanName);

    //Why need to iterator....

    Iterator<Bean<?>> itr = beans.iterator();

    while(itr.hasNext()) {

    Bean<?> bean = itr.next();

    String tempBeanName = bean.getName();

    if (tempBeanName.equals(beanName)) {

    clazz = bean.getBeanClass();

    break;

    }

    }

    return (T)(clazz != null ? container.select(clazz).get() : null);

}

/**

*<pre>

* Initialize Bean Manager

*</pre>

* @throws Exception

*/

private static void init() throws Exception {

if (container == null) {

synchronized(sync) {

    weld = new Weld();

    container = weld.initialize();

}

}


BeanUtil.java는 getBean Method에 beanName을 받아 객체를 Return한다.



특정 Class에서 Bean을 Inject하는 예제는 다음과 같다.

■ TextApplication.java

import java.io.BufferedReader;

import java.io.IOException;


import javax.inject.Inject;

import javax.inject.Named;



@Named("textApplication")

public class TextApplication {

@Inject

@Named("lowerCase")

private TextProcessor textProcessor;


@Inject

private BufferedReader reader;

public TextApplication() {

// this.textProcessor = textProcessor;

// this.userInputReader = new BufferedReader(new InputStreamReader(System.in));

// userInputReader.getBufferedReader();

}

public void run() throws IOException {

System.out.println("Enter the text to process : ");

String text = reader.readLine();

System.out.println(textProcessor.processText(text));

}



@Inject 과 @Named Annotation을 이용하여 필요한 Bean을 Field Level로 정의하여 

사용할 수 있다.



모든 필요 Clasa들이 만들었으면 테스트 프로그램을 만들어 테스트를 수행한다.


■Main.java

public class App 

{

    public static void main( String[] args ) throws Exception {


    TextApplication textApplication = BeanUtil.getBean("textApplication");

    textApplication.run();

   

    TextProcessor textProcessor = BeanUtil.getBean("lowerCase");

    System.out.println(textProcessor.processText("aaaaaa"));


    }

}