JSR 330: Dependency Injection for Java Example

JSR 330: Dependency Injection for Java เป็นการทำ DI(Dependency Injection) ใน Java สำหรับ JSR 330 ได้ Specification Leads จาก SpringSource คือ Rod Johnson ซึ่งเป็นคนสร้าง Spring Framework และ Co-Founder ของ SpringSource และ Bob Lee ผู้สร้าง Guice framework และได้รับรางวัล Jolt Awards (Java Collections Framework ของ Joshua Bloch ก็ได้รับรางวัลนี้เช่นเดียวกัน ซึ่ง Joshua Bloch ก็เป็นคนเขียนหนังสือยอดนิยมชื่อ Effective Java เมื่อกล่าวแบบนี้แล้วน่าจะพอคุ้นเคยกันบ้างนะครับ แต่เรื่องนี้ไม่ได้เกี่ยวกับ JSR 330 ที่กำลังพูดถึงอยู่ แค่เล่าให้ฟังเฉยๆ) สำหรับ Example นี้ผมจะแยกออกเป็นสามส่วนคือ DAO , Service และส่วนของ Servlet ซึ่งผมได้ทำการเพิ่ม Dependency ในโปรเจคผมตามนี้ครับ(โปรเจคเป็น maven project นะครับ)

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>JSR330</groupId>
	<artifactId>JSR330</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>3.1.2.RELEASE</version>
		</dependency>
	</dependencies>
	<build>
		<sourceDirectory>src</sourceDirectory>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.3.2</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

ซึ่งจะเห็นว่าผมแอดแค่ Spring-web เข้ามาใจโปรเจค เนื่องจากผมใช้ jboos 7 ในการรันทดสอบโปรเจคนี้นะครับและ jboos 7 ก็รองรับ jsr 330 แล้ว ถ้าหากว่าใช้ web server ตัวอื่นทดสอบให้ทำการเพิ่ม dependency ตัวด้านล่างเข้าไปด้วยครับ

	<dependency>
		<groupId>javax.inject</groupId>
		<artifactId>javax.inject</artifactId>
		<version>1</version>
	</dependency>

ใน Example นี้ผมจะใช้ JSR 330 ทำงานเทียบกับ Spring นะครับ ผมจะเขียนทั้งสองแบบเพื่อให้ดูว่ามันทำงานเหมือนกันอย่างไร โดยเริ่มที่ส่วนของ DAO

/*
* JSR 330
*/
package com.mockupcode.jsr330.dao;

import javax.inject.Named;

@Named
public class JsrDao {
	public String save(){
		return "JSR SAVED";
	}
}
/*
* Spring Framework
*/
package com.mockupcode.jsr330.dao;

import org.springframework.stereotype.Repository;

@Repository
public class SpringDao {
	public String save(){
		return "SPRING SAVED";
	}
}

จากโค๊ดสองตัวด้านบนจะเห็นว่าผมสร้างทุกอย่างเหมือนกันต่างกันแค่ที่ annotation ที่ใช้เท่านั้น ใน JSR 330 จะใช้คำว่า Named สำหรับประกาศ Bean ใน Ioc(Inversion of control) Context ส่วน Spring นั้นจะใช้ Repository(ตามตัวอย่าง) และยังสามารถใช้ Component,Service สำหรับประกาศ Bean ใน Ioc Context ซึ่งรายละเอียดของแต่ละ annotation ของ spring ในแนะนำให้อ่านจาก document ของ spring ครับเนื่องจากจะมีรายละเอียดเยอะ

ส่วนต่อไปจะเป็นส่วนของ Service ซึ่งจะแสดงโค๊ดตามด้านล่างครับ

/*
* JSR 330
*/
package com.mockupcode.jsr330.services;

import javax.inject.Inject;
import javax.inject.Named;

import com.mockupcode.jsr330.dao.JsrDao;

@Named
public class JsrService {
	@Inject
	private JsrDao jsrDao;
	
	public String saveTest(){
		return jsrDao.save();
	}
}
/*
* Spring Framework
*/
package com.mockupcode.jsr330.services;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.mockupcode.jsr330.dao.SpringDao;

@Service
public class SpringService {
	@Autowired
	private SpringDao springDao;
	
	public String saveTest(){
		return springDao.save();
	}
}

จากโค๊ดในส่วนของ Service นั้นแทบจะไม่ต่างอะไรกับ Spring เลยครับมีเพียงชื่อของ annotation เท่านั้นที่ไม่เหมือนกัน

สำหรับส่วนสุดท้ายคือส่วนแสดงผลซึ่งผมจะใช้ servlet จะมีโค๊ดดังนี้

package com.mockupcode.jsr330.servlet;

import java.io.IOException;
import java.io.PrintWriter;

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 org.springframework.web.context.support.WebApplicationContextUtils;

import com.mockupcode.jsr330.services.JsrService;
import com.mockupcode.jsr330.services.SpringService;

@WebServlet("/test")
public class Test extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		PrintWriter out = resp.getWriter();
		resp.setContentType("text/plain");
		
		SpringService springService = WebApplicationContextUtils.getWebApplicationContext(getServletContext()).getBean(SpringService.class);
		JsrService jsrService = WebApplicationContextUtils.getWebApplicationContext(getServletContext()).getBean(JsrService.class);
		
		out.println(springService.saveTest());
		out.println(jsrService.saveTest());
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req, resp);
	}

}

ในส่วนของ servlet ผมใช้ Util ของ spring ดึง Bean ของ jsr 330 และของ spring มาเพื่อแสดงผล ซึ่งตรงนี้แสดงให้เห็นว่า @Named นั้นถูกโหลดไปยัง Ioc Context เช่นเดียวกับ @Repository,@Component และ @Service ของ Spring แล้ว

* ใน Spring Container Bean จะมี Scope เป็น Singleton ซึ่งเราสามารถเปลี่ยนได้โดยใช้ @Scope
** ใน JSR 330 default scope จะเป็น Prototype
*** Bean ของ JSR 330 ที่ทำงานอยู่ใน Spring Container จะเป็น Singleton โดย Default
**** Configuration อื่นๆของโปรเจคนี้

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	version="3.0"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/applicationContext.xml</param-value>
	</context-param>

	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>

applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">

	<context:component-scan base-package="com.mockupcode.jsr330" />

</beans>


me on google plus+Jirawong Wongdokpuang

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s