<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Welcome to XP Link Co., Ltd. &#187; Spring Framework</title>
	<atom:link href="http://www.xp-link.com/category/spring-framework/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.xp-link.com</link>
	<description>XP Link Co., Ltd is a software consultant company specializes in Java Technology from Thailand.</description>
	<lastBuildDate>Tue, 10 Jan 2012 09:11:09 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>เพิ่มความสามารถในการ Cache ให้ Hibernate ด้วย EhCache</title>
		<link>http://www.xp-link.com/2011/08/30/hibernate-caching-with-ehcache/</link>
		<comments>http://www.xp-link.com/2011/08/30/hibernate-caching-with-ehcache/#comments</comments>
		<pubDate>Tue, 30 Aug 2011 11:06:29 +0000</pubDate>
		<dc:creator>nuttarut</dc:creator>
				<category><![CDATA[Spring Framework]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.xp-link.com/?p=511</guid>
		<description><![CDATA[ในการใช้งานฐานข้อมูล (Database) โดยทั่วไปนั้นจะมีข้อมูลบางส่วนที่มีการเปลี่ยนแปลงไม่บ่อยนัก หรือไม่มีการเปลี่ยนแปลงเลย แต่ฐานข้อมูลก็ต้องมีการทำงานทุกครั้งที่มีการเข้าถึงข้อมูลเหล่านี้ ทำให้อาจเสียเวลาในการประมวลผลไปโดยเปล่าประโยชน์ หรือในกรณีของระบบที่มีการทำงานหนักมากก็อาจจะทำให้ระบบขัดข้องเนื่องจากฐานข้อมูลไม่สามารถตอบสนองต่อการเข้าถึงข้อมูลได้ทันเวลา ปัญหานี้สามารถแก้ไขได้โดยวิธีที่เรียกว่า Cache ซึ่งนำข้อมูลที่ไม่ค่อยมีการเปลี่ยนแปลงเหล่านี้มาเก็บไว้ในหน่อยความจำ เพื่อที่เมื่อมีการเข้าถึงข้อมูลชุดเดิมก็ไม่ต้องไปค้นหาในฐานข้อมูลอีกครั้ง แต่มาดึงไปใช้จากหน่วยความจำแทน ซึ่งใช้เวลาน้อยกว่าและไม่เพิ่มภาระให้ฐานข้อมูลโดยไม่จำเป็น ข้างต้นคือแนวคิดในภาพรวม ส่วนรายละเอียดและขั้นตอนในการใช้ Cache นั้นก็ขึ้นกับเทคโนโลยีในระบบที่เราเลือกใช้ สำหรับในบทความนี้เราจะมาดูว่าถ้าต้องการใช้ Cache ในระบบที่พัฒนาด้วย Java และใช้เฟรมเวิร์คอย่าง Spring และ Hibernate นั้นควรจะต้องพิจรณาอะไรบ้าง ควรใช้อะไรในการทำ Cache? สำหรับ Hibernate ซึ่งเป็นเฟรมเวิร์คที่ช่วยจัดการในเรื่องฐานข้อมูลนั้นก็มีตัวเลือกในการใช้ Cache มากมาย แต่ตัวเลือกที่น่าจะเหมาะสมที่สุดก็คงไม่พ้น EhCache เนื่องจากสามารถใช้งานร่วมกับทั้ง Hibernate แล้ว Spring ได้อย่างไม่มีปัญหา (หรือมีน้อยมาก) และทีมพัฒนาของทั้ง Hibernate และ EhCache ก็ยังทำงานร่วมกันเพื่อรับประกันว่าเฟรมเวิร์คทั้งสองจะสามารถใช้งานร่วมกันได้อย่างราบรื่น ไม่เกิดปัญหาความเข้ากันไม่ได้ ข้อมูลส่วนใดบ้างที่ควรทำ Cache ก่อนอื่นต้องทำความเข้าใจก่อนว่า Hibernate นั้นจะมี Cache อยู่ 2 [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.xp-link.com/website/wp-content/uploads/2011/08/graph7.jpg" alt="" width="300" height="231" class="aligncenter size-full wp-image-544" /><br />
<br />
ในการใช้งานฐานข้อมูล (Database) โดยทั่วไปนั้นจะมีข้อมูลบางส่วนที่มีการเปลี่ยนแปลงไม่บ่อยนัก หรือไม่มีการเปลี่ยนแปลงเลย แต่ฐานข้อมูลก็ต้องมีการทำงานทุกครั้งที่มีการเข้าถึงข้อมูลเหล่านี้ ทำให้อาจเสียเวลาในการประมวลผลไปโดยเปล่าประโยชน์ หรือในกรณีของระบบที่มีการทำงานหนักมากก็อาจจะทำให้ระบบขัดข้องเนื่องจากฐานข้อมูลไม่สามารถตอบสนองต่อการเข้าถึงข้อมูลได้ทันเวลา<br />
<span id="more-511"></span><br />
<br />
ปัญหานี้สามารถแก้ไขได้โดยวิธีที่เรียกว่า Cache ซึ่งนำข้อมูลที่ไม่ค่อยมีการเปลี่ยนแปลงเหล่านี้มาเก็บไว้ในหน่อยความจำ เพื่อที่เมื่อมีการเข้าถึงข้อมูลชุดเดิมก็ไม่ต้องไปค้นหาในฐานข้อมูลอีกครั้ง แต่มาดึงไปใช้จากหน่วยความจำแทน ซึ่งใช้เวลาน้อยกว่าและไม่เพิ่มภาระให้ฐานข้อมูลโดยไม่จำเป็น<br />
<br />
ข้างต้นคือแนวคิดในภาพรวม ส่วนรายละเอียดและขั้นตอนในการใช้ Cache นั้นก็ขึ้นกับเทคโนโลยีในระบบที่เราเลือกใช้ สำหรับในบทความนี้เราจะมาดูว่าถ้าต้องการใช้ Cache ในระบบที่พัฒนาด้วย Java และใช้เฟรมเวิร์คอย่าง Spring และ Hibernate นั้นควรจะต้องพิจรณาอะไรบ้าง<br />
<br />
<strong>ควรใช้อะไรในการทำ Cache?</strong><br />
<br />
สำหรับ Hibernate ซึ่งเป็นเฟรมเวิร์คที่ช่วยจัดการในเรื่องฐานข้อมูลนั้นก็มีตัวเลือกในการใช้ Cache มากมาย แต่ตัวเลือกที่น่าจะเหมาะสมที่สุดก็คงไม่พ้น EhCache เนื่องจากสามารถใช้งานร่วมกับทั้ง Hibernate แล้ว Spring ได้อย่างไม่มีปัญหา (หรือมีน้อยมาก) และทีมพัฒนาของทั้ง Hibernate และ EhCache ก็ยังทำงานร่วมกันเพื่อรับประกันว่าเฟรมเวิร์คทั้งสองจะสามารถใช้งานร่วมกันได้อย่างราบรื่น ไม่เกิดปัญหาความเข้ากันไม่ได้<br />
<br />
<strong>ข้อมูลส่วนใดบ้างที่ควรทำ Cache</strong><br />
<br />
ก่อนอื่นต้องทำความเข้าใจก่อนว่า Hibernate นั้นจะมี Cache อยู่ 2 ประเภทด้วยกันคือ</p>
<ol>
<li>Second Level Cache (L2 Cache) &#8211; ใช้เก็บ Entity โดยใช้ id เป็นคีย์หลักในการตรวจสอบข้อมูล</li>
<li>Query Cache &#8211; ใช้เก็บผลที่ได้จาก Query โดยจะใช้ SQL Statement เป็นคีย์หลัก</li>
</ol>
<p>โดย Second Level Cache (หรือ L2 Cache) นั้นยังแบ่งประเภทของข้อมูลเป็นอีก 3 ประเภทคือ</p>
<ol>
<li>READ_ONLY &#8211; ข้อมูลที่ไม่มีการเปลี่ยนแปลง</li>
<li>NONSTRICT_READ_WRITE &#8211; ข้อมูลที่การเปลี่ยนแปลงไม่บ่อยมาก</li>
<li>READ_WRITE &#8211; ข้อมูลที่มีการเปลี่ยนแปลงตลอดเวลา</li>
</ol>
<p>จะเห็นได้ว่านอกจากข้อมูลที่ไม่ค่อยมีการเปลี่ยนแปลงแล้ว เราก็สามารถใช้ Cache กับข้อมูลที่มีการเปลี่ยนแปลงบ่อยได้ด้วย แต่เนื่องจากเมื่อข้อมูลมีการเปลี่ยนแปลงแล้วจะต้องมีการปรับปรุงข้อมูลที่อยู่ใน Cache ด้วย ทำให้มีการทำงานเพิ่มมากขึ้น ฉะนั้นข้อมูลที่มีอัตราส่วนการเขียนมากกว่าการอ่าน หรือข้อมูลประเภท Transaction จึงไม่เหมาะสมที่จะใช้การ Cache<br />
<br />
ส่วน Query Cache นั้นจะเก็บผลลัพธ์ที่ได้จาก SQL Statement เอาไว้ เมื่อมีการเรียกเรียกใช้ SQL Statement เดิมก็จะนำผลลัพธ์ที่เก็บไว้มาใช้งาน จึงเหมาะกับ Query ที่ตรงไปตรงมาหรือมีเงื่อนไขไม่มากนัก เช่น ข้อมูลประเทศ หรือหมวดหมู่สินค้า ซึ่งมีโอกาสที่จะถูกเรียกซ้ำบ่อย สำหรับ Query ประเภทที่เงื่อนไขเยอะ เช่น การค้นหาแบบละเอียด อาจจะไม่เหมาะที่จะใช้ Cache เท่าไหร เพราะมีโอกาสถูกเรียกใช้ซ้ำน้อย ทำให้เปลืองพื้นที่ในหน่วยความจำ<br />
<br />
ข้อมูลเพิ่มเติม &#8211; <a href="http://www.ehcache.org/documentation/user-guide/hibernate" target="_blank">ehcache.org</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.xp-link.com/2011/08/30/hibernate-caching-with-ehcache/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>การใช้งาน Tapesty ร่วมกับ Spring Framework</title>
		<link>http://www.xp-link.com/2007/08/03/using_tapestry_with_spring/</link>
		<comments>http://www.xp-link.com/2007/08/03/using_tapestry_with_spring/#comments</comments>
		<pubDate>Fri, 03 Aug 2007 07:35:37 +0000</pubDate>
		<dc:creator>nuttarut</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring Framework]]></category>
		<category><![CDATA[Tapestry]]></category>

		<guid isPermaLink="false">http://www.xp-link.com/2007/08/03/%e0%b8%81%e0%b8%b2%e0%b8%a3%e0%b9%83%e0%b8%8a%e0%b9%89%e0%b8%87%e0%b8%b2%e0%b8%99-tapesty-%e0%b8%a3%e0%b9%88%e0%b8%a7%e0%b8%a1%e0%b8%81%e0%b8%b1%e0%b8%9a-spring-framework/</guid>
		<description><![CDATA[&#160;&#160;&#160;Tapestry เป็นเฟรมเวิร์คสำหรับพัฒนาเว็บแอพพลิเคชั่นด้วยจาวาที่มีประสิทธิภาพมากเฟรมเวิร์คหนึ่ง ด้วยการทำงานในรูปแบบ Component-Centric ที่มีความสามารถหลักๆคือทำให้เราสามารถนำโค๊ดเก่ามาใช้ใหม่ได้ ง่าย และยังมี HiveMind ที่ทำให้สามารถใช้แนวคิด Inversion of Control (IoC)ในการพัฒนาได้อีกด้วย &#160;&#160;&#160;แต่การพัฒนาแอพพลิเคชั่นด้วยแนวคิดแบบ IoC ในปัจจุบันนั้น การใช้ Spring Framework จะเป็นที่นิยมแพร่หลายมากกว่า ฉะนั้นถ้าเราสามารถนำ Spring Framework มาใช้งานร่วมกับ Tapestry ได้ ก็จะเป็นประโยชน์มากทีเดียว &#160;&#160;&#160;โชคดีที่ทั้ง Spring Framework และ Tapestry นั้นมีสถาปัตยกรรมที่ค่อนข้างจะยืดหยุ่น ทำให้การนำเฟรมเวิร์คอื่นๆมาใช้งานร่วมด้วยนั้นสามารถทำได้ง่าย และมีประสิทธิภาพ โดยการนำ Spring Framework และ Tapestry มาใช้งานร่วมกันสามารถทำได้ดังนี้ การ config web.xml &#160;&#160;&#160;ก่อนอื่นเราจะต้องทำให้เว็บแอพลิเคชั่นที่พัฒนาด้วย Tapestryของเรานั้นหาไฟล์ config ของ Spring ให้เจอเสียก่อนโดยใช้ listener ที่ชื่อ ContextLoaderListener โดยทำการเพิ่ม config [...]]]></description>
			<content:encoded><![CDATA[<p><!-- 		@page { size: 8.5in 11in; margin: 0.79in } 		P { margin-bottom: 0.08in } 	-->             &nbsp;&nbsp;&nbsp;<a href="http://tapestry.apache.org/">Tapestry</a> เป็นเฟรมเวิร์คสำหรับพัฒนาเว็บแอพพลิเคชั่นด้วยจาวาที่มีประสิทธิภาพมากเฟรมเวิร์คหนึ่ง ด้วยการทำงานในรูปแบบ  Component-Centric ที่มีความสามารถหลักๆคือทำให้เราสามารถนำโค๊ดเก่ามาใช้ใหม่ได้ ง่าย และยังมี <a href="http://hivemind.apache.org/">HiveMind</a> ที่ทำให้สามารถใช้แนวคิด Inversion of Control (IoC)ในการพัฒนาได้อีกด้วย<br />
<br />
<!-- 		@page { size: 8.5in 11in; margin: 0.79in } 		P { margin-bottom: 0.08in } 	-->   &nbsp;&nbsp;&nbsp;แต่การพัฒนาแอพพลิเคชั่นด้วยแนวคิดแบบ IoC ในปัจจุบันนั้น การใช้ <a href="http://www.springframework.org/">Spring Framework</a> จะเป็นที่นิยมแพร่หลายมากกว่า  ฉะนั้นถ้าเราสามารถนำ Spring Framework มาใช้งานร่วมกับ Tapestry ได้ ก็จะเป็นประโยชน์มากทีเดียว<br />
<br /><span id="more-29"></span><br />
<!-- 		@page { size: 8.5in 11in; margin: 0.79in } 		P { margin-bottom: 0.08in } 	--></p>
<p>&nbsp;&nbsp;&nbsp;โชคดีที่ทั้ง Spring Framework และ Tapestry นั้นมีสถาปัตยกรรมที่ค่อนข้างจะยืดหยุ่น ทำให้การนำเฟรมเวิร์คอื่นๆมาใช้งานร่วมด้วยนั้นสามารถทำได้ง่าย และมีประสิทธิภาพ โดยการนำ Spring Framework และ Tapestry มาใช้งานร่วมกันสามารถทำได้ดังนี้<br />
</p>
<h4>การ config web.xml</h4>
<p>&nbsp;&nbsp;&nbsp;ก่อนอื่นเราจะต้องทำให้เว็บแอพลิเคชั่นที่พัฒนาด้วย Tapestryของเรานั้นหาไฟล์ config ของ Spring ให้เจอเสียก่อนโดยใช้ listener ที่ชื่อ ContextLoaderListener โดยทำการเพิ่ม config ใน web.xml ดังนี้<br />
<br />
<!-- 		@page { size: 8.5in 11in; margin: 0.79in } 		P { margin-bottom: 0.08in } 	--></p>
<pre class="code">
&lt;listener&gt;
    	&lt;listener-class&gt;
                 org.springframework.web.context.ContextLoaderListener
        &lt;/listener-class&gt;
&lt;/listener&gt;
</pre>
<p>
<!-- 		@page { size: 8.5in 11in; margin: 0.79in } 		P { margin-bottom: 0.08in } 	--></p>
<p>
<!-- 		@page { size: 8.5in 11in; margin: 0.79in } 		P { margin-bottom: 0.08in } 	--><br />
&nbsp;&nbsp;&nbsp;ในส่วนต่อไปจะเป็นการทำให้ ContextLoaderListener ทราบว่าจะเข้าไปหาไฟล์ config ของ Spring ได้ที่ไหน ถ้าไม่มีการกำหนดในส่วนนี้ไว้ ContextLoaderListener  จะเข้าไปหาใน /WEB-INF/applicationContext.xml แทน</p>
<p>
<!-- 		@page { size: 8.5in 11in; margin: 0.79in } 		P { margin-bottom: 0.08in } 	--></p>
<pre class="code">
&lt;context-param&gt;
    	&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
    	&lt;param-value&gt;/WEB-INF/applicationContext*.xml&lt;/param-value&gt;
&lt;/context-param&gt;
</pre>
<h4>การใช้ Dependency Injection เพื่อเรียกใช้ Spring Bean</h4>
<p>&nbsp;&nbsp;&nbsp;เรามาสารถเรียกใช้ Spring Bean จาก page object ของ Tapestry ได้โดยตรงเช่น<br />
<br />
<!-- 		@page { size: 8.5in 11in; margin: 0.79in } 		P { margin-bottom: 0.08in } 	--></p>
<pre class="code">
WebApplicationContext appContext = WebApplicationContextUtils.getApplicationContext(
    getRequestCycle().getRequestContext().getServlet().getServletContext());
SomeService someService = (SomeService) appContext.getBean("someService");
</pre>
<p><!-- 		@page { size: 8.5in 11in; margin: 0.79in } 		P { margin-bottom: 0.08in } 	--><br />
<br />
&nbsp;&nbsp;&nbsp;แต่การทำแบบนี้จะทำให้แก้ไขลำบากในภายหลัง เพราะเราจะต้องแก้ทุก page object ที่เรียกใช้ Spring Bean และถึงแม้เราจะใช้รูปแบบการเขียนโค๊ดต่างๆ ที่จะสะดวกในการแก้ไขแล้วก็ตาม ตัว Servlet เองก็ไม่ควรเรียกใช้ Application Context โดยตรง หรือรู้ว่าถูกสร้างมาได้อย่างไร ตามหลักของ IoC<br />
<!-- 		@page { size: 8.5in 11in; margin: 0.79in } 		P { margin-bottom: 0.08in } 	--><br />
<br />
&nbsp;&nbsp;&nbsp;เราสามารถแก้ปัญหานี้ได้โดยใช้ไลบราลีที่ชื่อ <a href="http://sourceforge.net/projects/diaphragma">Tapestry-Spring</a> ซึ่งจะใช้ Annotation @InjectObject แทนการเรียกใช้แบบเดิมที่กล่าวไว้ข้างต้น ทำให้เราเรียกใช้ Spring Beanได้ง่ายและยืดหยุ่นมากยิ่งขึ้น โดยให้ทำการดาวน์โหลดไฟล์ไลบราลีมาใส่ไว้ร่วมกับไลบราลีอื่นๆ ที่เราใช้ในเว็บแอพพลิเคชั่น (ปกติจะเป็น /WEB-INF/lib) และทำการเรียกใช้ใน page object ดังนี้<br />
<!-- 		@page { size: 8.5in 11in; margin: 0.79in } 		P { margin-bottom: 0.08in } 	--><br />
</p>
<pre class="code">
@InjectObject("spring:someService")
public abstract SomeService getSomeService();
</pre>
<p><!-- 		@page { size: 8.5in 11in; margin: 0.79in } 		P { margin-bottom: 0.08in } 	--><br />
<br />
&nbsp;&nbsp;&nbsp;สำหรับระบบที่ไม่ได้ใช้ Java5 จะต้องทำการเรียกใช้ Spring Bean ผ่านไฟล์ .page หรือ .jwc ของหน้าเว็บนั้นๆแทนดังนี้<br />
<!-- 		@page { size: 8.5in 11in; margin: 0.79in } 		P { margin-bottom: 0.08in } 	--><br />
</p>
<pre class="code">
&lt;inject property="someService" object="spring:someService"/&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.xp-link.com/2007/08/03/using_tapestry_with_spring/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ข้อแตกต่างระหว่าง BeanFactory และ ApplicationContext</title>
		<link>http://www.xp-link.com/2006/07/31/different_beanfactory_n_applicationcontext/</link>
		<comments>http://www.xp-link.com/2006/07/31/different_beanfactory_n_applicationcontext/#comments</comments>
		<pubDate>Mon, 31 Jul 2006 11:25:40 +0000</pubDate>
		<dc:creator>siros</dc:creator>
				<category><![CDATA[Spring Framework]]></category>

		<guid isPermaLink="false">http://www.xp-link.com/website/2006/07/31/different_beanfactory_n_applicationcontext/</guid>
		<description><![CDATA[ Question BeanFactory และ ApplicationContext ต่างกันอย่างไร เมื่อใดควรจะใช้ BeanFactory เมื่อใดควรจะใช้ ApplicationContext Answer BeanFactory และ ApplicationContext ต่างก็เป็น interface ของ implementation ที่เป็น bean container ซึ่งโดยทั่วไป application code จะใช้ interface ทั้งสองตัวนี้ ในการ access object ที่สร้างมาจาก bean definition ข้อแตกต่างของทั้งสองตัวนี้ อยู่ที่ feature ของ implementation โดย ApplicationContext นั้นเป็น interface ที่ขยายต่อเติมออกมาจาก BeanFactory เพื่อเพิ่ม feature หลายๆ อย่างเข้าไป โดยสามารถสรุปเป็นหัวข้อได้ดังนี้ Default Initialization Mode MessageSource Event Propagation ResourceLoader [...] ]]></description>
			<content:encoded><![CDATA[<h3>Question</h3>
<p>BeanFactory และ ApplicationContext ต่างกันอย่างไร เมื่อใดควรจะใช้ BeanFactory เมื่อใดควรจะใช้ ApplicationContext <br/><br/></p>
<h3>Answer</h3>
<p>BeanFactory และ ApplicationContext ต่างก็เป็น interface ของ implementation ที่เป็น bean container ซึ่งโดยทั่วไป application code จะใช้ interface ทั้งสองตัวนี้ ในการ access object ที่สร้างมาจาก bean definition <br/><br/></p>
<p>ข้อแตกต่างของทั้งสองตัวนี้ อยู่ที่ feature ของ implementation โดย ApplicationContext นั้นเป็น interface ที่ขยายต่อเติมออกมาจาก BeanFactory เพื่อเพิ่ม feature หลายๆ อย่างเข้าไป โดยสามารถสรุปเป็นหัวข้อได้ดังนี้ <br/><br/></p>
<p><span id="more-20"></span></p>
<ul >
<li>Default Initialization Mode</li>
<li>MessageSource</li>
<li>Event Propagation</li>
<li>ResourceLoader</li>
<li>Web Application Integration</li>
<li>Extension Point</li>
</ul>
<h4>Default Initialization Mode</h4>
<p >
Bean definition ที่ถูก load โดย BeanFactory จะมี initialization mode โดย default เป็นแบบ lazy นั่นคือ จะยังไม่มีการสร้าง object ของ bean definition ขึ้นมาจนกว่าจะมีความจำเป็นต้องใช้ object นั้น (นั่นคือ เมื่อมีการ call getBean ด้วย id ของ bean definition นั้นๆ หรือ เมื่อมีการสร้าง object ซึ่งมี reference ไปหา bean definition นั้นๆ) <br/><br/></p>
<p>แต่สำหรับ ApplicationContext จะมีค่า default ของ initialization mode ของ bean definition เป็น eager นั่นคือ จะมีการสร้าง object สำหรับ bean definition ที่มี scope เป็น singleton ทันที เมื่อสร้าง instance ของ ApplicationContext<br/><br/></p>
<p>อย่างไรก็ตาม ค่า initialization mode นี้ สามารถกำหนดได้ด้วย attribute ?lazy-init? บน element ?bean? สำหรับ bean definition แต่ละตัว หรือ ด้วย attribute ?default-lazy-init? บน root element ?beans? สำหรับทุกๆ bean definition ภายใต้ root element นั้น<br/><br/></p>
<h4>MessageSource</h4>
<p >ApplicationContext นั้น extend มาจาก interface MessageSource ซึ่งใช้สำหรับให้บริการด้าน message ซึ่งเป็น internationalization หรือ i18n โดยที่เมื่อสร้าง instance ของ ApplicationContext จะมีการหา instance ของ MessageSource ซึ่งถูก define ไว้ภายใต้ ApplicationContext นั้น จาก id ?messageSource? โดยที่ instance ที่ได้นี้ จะใช้สำหรับให้บริการด้าน message ซึ่งจะ delegate มาจาก ApplicationContext หรืออีกนัยหนึ่ง การ call method ที่เกี่ยวกับ i18n message บน instance ของ ApplicationContext จะทำให้เกิดการ call method บน instance ของ MessageSource นี้อีกทอดหนึ่ง <br/><br/></p>
<p>ตัวอย่างด้านล่างนี้แสดงการเขียน bean definition สำหรับ message source ซึ่งใช้ class ResourceBundleMessageSource โดยที่ class นี้จะใช้การทำงานของ ResourceBundle เพื่อให้บริการ message (สามารถอ่านรายละเอียดเกี่ยวกับการใช้งาน ResourceBundle ได้จาก Java API document)<br/><br/></p>
<pre class="code">
&lt;bean id="messageSource"
  class="org.springframework.context.support.ResourceBundleMessageSource" &gt;

    &lt;property name="basenames"&gt;
        &lt;list&gt;
            &lt;value&gt;common&lt;/value&gt;
            &lt;value&gt;error&lt;/value&gt;
        &lt;/list&gt;
    &lt;/property&gt;
&lt;/bean&gt;
</pre>
<p>เมื่อเรามี bean definition ที่เป็น message source ใน ApplicationContext แล้ว เราสามารถอ่าน message มาใช้งานได้ โดยใช้ method ?getMessage()? ตัวใดตัวหนึ่งจาก MessageSource ดังแสดงในตัวอย่างด้านล่าง<br/><br/></p>
<pre class="code">
ApplicationContext ctx;
Locale locale = Locale.ENGLISH;
...

System.out.println(
ctx.getMessage(?mandatory.missing?, new Object(?First Name?), locale));
</pre>
<p>จากไฟล์ resource bundle นี้ เมื่อตัวอย่าง code ทำงานแล้ว จะได้ผลลัพธ์ดังนี้ <br/><br/></p>
<pre class="code">
Value of field ?First Name? is required.
</pre>
<h4>Event Propagation</h4>
<p>ใน ApplicationContext สามารถกำหนดให้ object ที่สร้างขึ้น ทำหน้าที่เป็น event listener ได้ โดยให้ class ของ object นั้น implement interface ApplicationListener ดังแสดงในตัวอย่าง<br/><br/></p>
<pre class="code">
import org.springframework.context.ApplicationListener;
import org.springframework.context.ApplicationEvent;

public class MyListener implements ApplicationListener {

    public void onApplicationEvent(ApplicationEvent event) {

        // Handle event
    }
}
</pre >

ApplicationContext จะตรวจสอบว่า object ตัวใดบ้างที่เป็น event listener และเมื่อเกิด event ขึ้น จะ notify event listener ทุกตัวใน Spring เองมี event ด้วยกัน 3 ตัว คือ ContextRefreshedEvent ContextClosedEvent และ RequestHandledEvent นอกจาก event 3 ตัวนี้แล้ว สามารถเขียน code เพื่อสร้าง event ขึ้นมาเองได้ตามต้องการ ดังแสดงตัวอย่างด้านล่าง<br/><br/>
<pre class="code">
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;

public class MyEventPublisher implements ApplicationContextAware {

    private ApplicationContext ctx;

    public void setApplicationContext(ApplicationContext ctx) {
        this.ctx = ctx;
    }

    public void publishMyEvent() {

        // Create an instance of ApplicationEvent
        ApplicationEvent event = ...
        // Publish
        ctx.publishEvent(event);
    }
}
</pre>
<p>จากตัวอย่าง class ที่เราเขียนขึ้นมานั้น implement interface ApplicationContextAware เพื่อให้ ApplicationContext ส่ง instance ของตัวมันเองมาเป็น argument ของ method "setApplicationContext()" เพราะเราจำเป็นต้องใช้ instance ของ ApplicationContext เพื่อ call method "publishEvent()" <br/><br/></p>
<h4>ResourceLoader</h4>
<p>ใน Spring จะมีใช้ interface "Resource" เป็น abstraction API ที่ใช้ access low-level resource ซึ่งได้แก่ <br/><br/></p>
<ul >
<li>ไฟล์จาก local file system</li>
<li>ไฟล์จาก classpath</li>
<li>resource จาก URL</li>
<li>อื่นๆ</li>
</ul>
<p>ที่มาของ interface Resource นั้นเนื่องมาจากว่า ยังไม่มี standard Java API ตัวใดที่ทำหน้าที่เป็น abstraction API ของการ access resource ทั้งหมดที่ได้ยกตัวอย่างมาได้ (เช่น class URL ไม่สามารถใช้กับ resource จาก classpath ได้) <br/><br/></p>
<p>ApplicationContext นั้น extend มาจาก interface ResourceLoader ซึ่งทำหน้าที่ในการสร้าง instance ของ Resource ตาม resource path ที่กำหนด ดังนั้น เราจึงสามารถใช้ ApplicationContext ในการ access resource ตามที่เราต้องการได้ ดังตัวอย่างด้านล่าง <br/><br/></p>
<pre class="code">
ApplicationContext ctx;
...

Resource res = ctx.getResource(?classpath:com/xplink/resource.dat?);
InputStream in = res.getInputStream();
</pre>
<p>นอกจากนี้ ApplicationContext ยังมีความสามารถในการหา resource ตาม ?ชนิด? ของ ApplicationContext หากเราไม่กำหนด prefix ใน resource path เช่นในตัวอย่างด้านล่าง ApplicationContext ถูกสร้างขึ้นมาโดยใช้ bean definition จาก classpath เมื่อทำการ access resource ที่ไม่ได้กำหนด prefix มันจึงหา resource นั้นจาก classpath ด้วย<br/><br/></p>
<pre  class="code">
ApplicationContext ctx = new ClassPathXmlApplicationContext(?bean.xml?);

Resource res = ctx.getResource(?com/xplink/resource.dat?);
</pre>
<h4>Web Application Integration</h4>
<p>โดยปกติแล้ว instance ของ BeanFactory นั้นต้องถูกสร้างขึ้นด้วยการเขียน code เองเสมอ แต่ว่า ApplicationContext นั้นสามารถถูก initialize ได้โดยอัตโนมัติ เมื่ออยู่ใน Java Servlet Container โดยตัว Listener หรือ Servlet ที่ configure ไว้ในไฟล์ web.xml จะทำหน้าที่ในการสร้าง instance ของ ApplicationContext จากไฟล์ bean definition ที่กำหนดด้วย context parameter (ใน web.xml) ชื่อ "contextConfigLocation" ดังแสดงในตัวอย่างด้านล่าง <br/><br/></p>
<pre class="code">
&lt;context-param&gt;
    &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
    &lt;param-value&gt;
        /WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml
    &lt;/param-value&gt;
&lt;/context-param&gt;
</pre>
<p>ค่าของ "contextConfigLocation" นั้นเป็น list ของ location ของไฟล์ bean definition ซึ่งคั่นด้วย space comma หรือ semi-colon ซึ่งค่า context parameter นี้เป็น optional หากไม่มีการระบุค่านี้ในไฟล์ web.xml ไฟล์ "/WEB-INF/applicationContext.xml" จะถูกนำมาใช้สร้าง ApplicationContext <br/><br/></p>
<p>สำหรับ Container ที่ support Listener (Container ที่ implement ตาม Servlet specification version  2.4 หรือ Container ที่ support version 2.3 บางตัว) สามารถใช้ ContextLoaderListener เพื่อ initialize ApplicationContext ได้ดังแสดงในตัวอย่างด้านล่าง <br/><br/></p>
<pre class="code">
&lt;listener&gt;
    &lt;listener-class&gt;
        org.springframework.web.context.ContextLoaderListener
    &lt;/listener-class&gt;
&lt;/listener&gt;
</pre>
<p>สำหรับ Container ที่ไม่ support Listener สามารถใช้ ContextLoaderServlet เพื่อ initialize ApplicationContext ได้แทน โดยใช้ configuration ดังแสดงด้านล่าง<br/><br/></p>
<pre class="code">
&lt;servlet&gt;
    &lt;servlet-name&gt;context&lt;/servlet-name&gt;
    &lt;servlet-class&gt;
        org.springframework.web.context.ContextLoaderServlet
    &lt;/servlet-class&gt;
    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
&lt;/servlet&gt;
</pre>
<p>instance ของApplicationContext ที่ถูกสร้างขึ้นนี้จะถูกเก็บไว้ใน ServletContext ภายใต้ชื่อ WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE โดยสามารถใช้ method getWebApplicationContext จาก class WebApplicationContextUtils เพื่อ access instance ของ ApplicationContext นั้นๆ ได้ ตามตัวอย่างด้านล่าง<br/><br/></p>
<pre class="code">
import javax.servlet.ServletRequest;
import javax.servlet.ServletContext;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

...

// Inside servlet
ServletContext ctx = this.getServletConfig().getServletContext();
WebApplicationContext webAppCtx =
    WebApplicationContextUtils.getWebApplicationContext(ctx);
</pre>
<p>
สำหรับกรณีที่ใช้ web framework ที่สามารถ integrate เข้ากับ Spring ได้นั้น เราอาจไม่จำเป็นต้องเขียน code เพื่อ access ApplicationContext โดยตรงเหมือนในตัวอย่างข้างบน เช่น หากใช้ Spring integrate กับ JSF เราสามารถ inject object จาก Spring bean definition เข้าไปที่ managed bean ของ JSF ได้เลย<br/><br/></p>
<h4>Extension Point</h4>
<p>ใน BeanFactory และ ApplicationContext นั้นมี extension point อยู่ โดยที่สามารถสร้าง extension เข้าไปทำงานเพิ่มเข้าไป ณ ที่ extension point นั้นได้ เพื่อให้หน้าที่บางอย่างเพิ่มเติมจากสิ่งที่ BeanFactory และ ApplicationContext มีอยู่แล้ว<br/><br/></p>
<p>สำหรับ BeanFactory นั้น จะต้อง register extension ประเภท BeanPostProcessor และ BeanFactoryPostProcessor กับ  instance ของ BeanFactory ก่อน extension นั้นจึงจะทำงานได้ ตัวอย่างด้านล่างแสดงการ register BeanPostProcessor กับ BeanFactory<br/><br/></p>
<pre class="code">
// Create an instance of implementation of ConfigurableBeanFactory
ConfigurableBeanFactory factory = ...

// Create an instance of implementation of BeanPostProcessor
BeanPostProcessor postProcessor = ...

// Register BeanPostProcessor to BeanFactory
factory.addBeanPostProcessor(postProcessor);
</pre>
<p>แต่สำหรับ ApplicationContext นั้น ไม่จำเป็นต้องเขียน code เพื่อ register extension เหล่านี้ เพราะ implementation ของ ApplicationContext นั้นสามารถค้นหา bean definition ของตัวเองที่เป็น extension และ register extension เหล่านี้ให้โดยอัตโนมัติ นั่นคือ ไม่จำเป็นต้องเขียน code เพื่อสร้าง instance เหล่านี้ขึ้นมาเพื่อ register กับ ApplicationContext เหมือนใน BeanFactory เพียงแค่สร้าง bean definition ของ extension ที่ต้องการไว้ในใน configuration ที่ใช้สร้าง instance ของ ApplicationContext นั้นๆ extension ที่ถูกสร้างจาก bean definition นั้นก็จะถูก register เข้ากับ ApplicationContext โดยอัตโนมัติเมื่อสร้าง instance ของ extension<br/><br/></p>
<h4>Summary</h4>
<p>implementation ของ ApplicationContext นั้น ให้ feature ที่เพิ่มเติมไปจาก implementation ของ BeanFactory อยู่หลายตัว สำหรับกรณีทั่วไป ที่ไม่มีประเด็นเรื่อง resource ของ runtime environment ที่มีจำกัดมากๆ ApplicationContext เป็นตัวเลือกที่ค่อนข้างเหมาะสมกับการใช้งานมากกว่า โดยเฉพาะเมื่อพิจารณาถึง feature ที่มีเพิ่มขึ้นมาจาก BeanFactory แต่สำหรับกรณีที่ resource (processor และ memory) มีจำกัดมากๆ BeanFactory อาจจะเป็นตัวเลือกที่ดีกว่า เนื่องจากความเหมาะสมทางด้านการใช้งานทรัพยากร ซึ่งด้วย feature ที่น้อยกว่า implementation ของ BeanFactory จะมีแนวโน้มการใช้ memory ที่น้อยกว่า นอกจากนั้นการใช้ lazy initialization จะช่วยประหยัดทั้ง processing time ขณะ initialization และประหยัด memory ที่ใช้สำหรับเก็บ singleton bean</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xp-link.com/2006/07/31/different_beanfactory_n_applicationcontext/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

