﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-爪哇一角 ( 孙 琳 的 博 客 )-文章分类-spring</title><link>http://www.blogjava.net/ocean07000814/category/15456.html</link><description>共同探讨STRUTS#HIBERNATE#SPRING#EJB等技术</description><language>zh-cn</language><lastBuildDate>Fri, 02 Mar 2007 03:26:48 GMT</lastBuildDate><pubDate>Fri, 02 Mar 2007 03:26:48 GMT</pubDate><ttl>60</ttl><item><title>Ioc容器的革命性优点(转)</title><link>http://www.blogjava.net/ocean07000814/articles/70690.html</link><dc:creator>非洲小白脸</dc:creator><author>非洲小白脸</author><pubDate>Wed, 20 Sep 2006 01:31:00 GMT</pubDate><guid>http://www.blogjava.net/ocean07000814/articles/70690.html</guid><wfw:comment>http://www.blogjava.net/ocean07000814/comments/70690.html</wfw:comment><comments>http://www.blogjava.net/ocean07000814/articles/70690.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ocean07000814/comments/commentRss/70690.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ocean07000814/services/trackbacks/70690.html</trackback:ping><description><![CDATA[
		<h3 align="center">Ioc容器的革命性优点</h3>
		<p>　　我们知道，在Java基本教程中有一个定律告诉我们：所有的对象都必须创建；或者说：使用对象之前必须创建，但是现在我们可以不必一定遵循这个定律了，我们可以从Ioc容器中直接获得一个对象然后直接使用，无需事先创建它们。</p>
		<p>　　这种变革，就如同我们无需考虑对象销毁一样；因为Java的垃圾回收机制帮助我们实现了对象销毁；现在又无需考虑对象创建，对象的创建和销毁都无需考虑了，这给编程带来的影响是巨大的。</p>
		<p>　　我们从一个简单例子开始，有一个普通类B代码如下：</p>
		<table width="100%" bgcolor="#cccccc" border="0">
				<tbody>
						<tr>
								<td>public class B implements BI{ 
<p>　　　　AInfterface a; </p><p>　　　　public B(AInfterface a){</p><p>　　　　　　this.a = a </p><p>　　　　} </p><p>　　　　public void invoke(){ </p><p>　　　　　　/** ...*/ </p><p>　　　　} </p><p>} </p><p> </p><p></p></td>
						</tr>
				</tbody>
		</table>
		<p>　　有两种使用B的方式：</p>
		<p>　　普通无Ioc容器的调用方式: <br />　　BI b = new B(<strong>new A()</strong>);//需要在生成B实例之前 生成A等实例<br />　　b. invoke();</p>
		<div style="mso-line-spacing: '80 20 0'; mso-margin-left-alt: 216; mso-char-wrap: 1; mso-kinsoku-overflow: 1">
				<p>　　使用Ioc容器(<a href="http://www.jdon.com/jdonframework/index.htm" target="_blank">Jdon框架</a>)的革命调用方式：<br />　　BI b = (BI) WebAppUtil.getService(“b”);<br />　　b. invoke();<br /><br />　　上面两种方式重要区别：<br />　　前者需要照顾B类中A类的实例化，如果B类中调用不只A类一个，还有更多其他类如C/D/E等类，这样，你在使用B类时，还需要研究其他类的创建，如果C/D/E这些类不是你自己编写，你还需要翻阅它们的API说明，研究它们应该如何创建？是使用New 还是工厂模式 还是单态调用？</p>
				<p>　　这时，你会感叹：哇，有没有搞错？我只不过是为了使用B类中一个小小的方法，就花去我这么多时间和精力？</p>
				<p>　　当我们使用第二种方式时，就无需花很多精力和时间考虑A/C/D/E等类的创建。</p>
				<p>　　使用Ioc容器，你再也不必做这些僵化愚蠢的工作了，我们只需从ioc容器中抓取一个类然后直接使用它们。</p>
				<p>　　当然，在使用之前，我们需要做一个简单的配置，把你将来需要使用的类全部告诉ioc容器，例如<a href="http://www.jdon.com/jdonframework/index.htm" target="_blank">Jdon框架</a>的ioc容器配置jdonframework.xml如下:</p>
				<p>&lt;app&gt;<br />　　&lt;services&gt;<br />　　　　&lt;pojoService name="b" class="test.B"/&gt;<br />　　　　&lt;pojoService name="a" class="test.A"/&gt;<br />　　　　&lt;pojoService name="c" class="test.C"/&gt;<br /><br />　　&lt;/services&gt;<br />&lt;/app&gt;</p>
				<p>　　注意：虽然B类代码调用了A类(甚至可能调用C等其他类)，但是在配置中我们无需考虑这种调用关系。因此，整个环节我们都无需考虑B类中涉及其他类的调用关系；这样是非常省时省力的；特别是如果项目较大，JavaBeans特别多，又是多人协调开发，这种方式对提高开发效率；降低出错率是非常大的帮助。</p>
				<p>　　如果你的项目中有非常多的类；调用关系很复杂，而且调用关系随时都可能变化，那么，使用无需照顾调用关系的Ioc容器无疑是减轻开发负担的首选。</p>
				<p>　　ioc容器另外一个著名实现是Spring框架，但是在Spring的配置文件applicationContext.xml中，我们必须考虑上述调用关系：</p>
				<p>&lt;bean id="b" class="test.B"&gt;<br />　　&lt;property name="a"&gt;<strong>&lt;ref bean="a"/&gt;</strong>&lt;/property&gt;&lt;!-- <strong>必须指定调用关系</strong> --&gt; <br />　　....<br />&lt;/bean&gt;<br />&lt;bean id="a" class="test.A"&gt;<br />&lt;bean id="c" class="test.C"&gt; </p>
				<p>　　所以，从以上对比来看，从项目开发效率角度看，基于PiocContainer实现的Jdon框架在实际使用配置效率无疑要高于Spring框架。</p>
				<p>　　同时，也可以说：基于PiocContainer实现的Jdon框架完全真正实现了Ioc容器的革命性优点：颠覆了“使用对象之前必须创建” 的基本Java语言定律</p>
		</div>
<img src ="http://www.blogjava.net/ocean07000814/aggbug/70690.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ocean07000814/" target="_blank">非洲小白脸</a> 2006-09-20 09:31 <a href="http://www.blogjava.net/ocean07000814/articles/70690.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ioc模式(转)</title><link>http://www.blogjava.net/ocean07000814/articles/70689.html</link><dc:creator>非洲小白脸</dc:creator><author>非洲小白脸</author><pubDate>Wed, 20 Sep 2006 01:30:00 GMT</pubDate><guid>http://www.blogjava.net/ocean07000814/articles/70689.html</guid><wfw:comment>http://www.blogjava.net/ocean07000814/comments/70689.html</wfw:comment><comments>http://www.blogjava.net/ocean07000814/articles/70689.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ocean07000814/comments/commentRss/70689.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ocean07000814/services/trackbacks/70689.html</trackback:ping><description><![CDATA[
		<h3 align="center">Ioc模式(又称DI：Dependency Injection)</h3>
		<p align="left">　　分离关注（ Separation of Concerns : SOC）是Ioc模式和AOP产生最原始动力，通过功能分解可得到关注点，这些关注可以是 组件Components, 方面Aspects或服务Services。</p>
		<p align="left">　　从GoF设计模式中，我们已经习惯一种思维编程方式：Interface Driven Design 接口驱动，接口驱动有很多好处，可以提供不同灵活的子类实现，增加代码稳定和健壮性等等，但是接口一定是需要实现的，也就是如下语句迟早要执行：</p>
		<p align="left">　　AInterface a = new AInterfaceImp(); </p>
		<p align="left">　　AInterfaceImp是接口AInterface的一个子类，Ioc模式可以延缓接口的实现，根据需要实现，有个比喻：接口如同空的模型套，在必要时，需要向模型套注射石膏，这样才能成为一个模型实体，因此，我们将人为控制接口的实现成为“注射”。</p>
		<p align="left">　　Ioc英文为 Inversion of Control，即反转模式，这里有著名的好莱坞理论：你呆着别动，到时我会找你。</p>
		<p align="left">　　其实Ioc模式也是解决调用者和被调用者之间的一种关系，上述AInterface实现语句表明当前是在调用被调用者AInterfaceImp，由于被调用者名称写入了调用者的代码中，这产生了一个接口实现的原罪：彼此联系，调用者和被调用者有紧密联系，在UML中是用依赖 Dependency 表示。</p>
		<p align="left">　　但是这种依赖在分离关注的思维下是不可忍耐的，必须切割，实现调用者和被调用者解耦，新的Ioc模式 Dependency Injection 模式由此产生了， Dependency Injection模式是依赖注射的意思，也就是将依赖先剥离，然后在适当时候再注射进入。</p>
		<p align="left">Ioc模式（Dependency Injection模式）有三种：</p>
		<table cellspacing="2" cellpadding="2" width="100%" border="1">
				<tbody>
						<tr>
								<td width="20%">第一种类型</td>
								<td width="46%">从JNDI或ServiceManager等获得被调用者，这里类似ServiceLocator模式。</td>
								<td width="34%">1. EJB/J2EE<br />2. Avalon（Apache的一个复杂使用不多的项目）</td>
						</tr>
						<tr>
								<td>第二种类型</td>
								<td>使用JavaBeans的setter方法</td>
								<td>1. Spring Framework,<br />2. WebWork/XWork</td>
						</tr>
						<tr>
								<td>第三种类型</td>
								<td>在构造方法中实现依赖</td>
								<td>1. PicoContainer,<br />2. HiveMind</td>
						</tr>
				</tbody>
		</table>
		<p>　　有过EJB开发经验的人都知道，每个EJB的调用都需要通过JNDI寻找到工厂性质的Home接口，在我的教程<a href="http://www.jdon.com/ejbtur.htm" target="_blank">EJB是什么</a>章节中，我也是从依赖和工厂模式角度来阐述EJB的使用。</p>
		<p>　　在通常传统情况下，为了实现调用者和被调用者解耦，分离，一般是通过工厂模式实现的，下面将通过比较工厂模式和Ioc模式不同，加深理解Ioc模式。</p>
		<h4>工厂模式和Ioc</h4>
		<p>　　假设有两个类B 和 C：B作为调用者，C是被调用者，在B代码中存在对C的调用：</p>
		<table bordercolor="#cccccc" cellspacing="2" cellpadding="2" width="80%" bgcolor="#cccccc" border="0">
				<tbody>
						<tr>
								<td>
										<p>public class B{<br />　　 private C comp; <br />　　......<br />} </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>　　实现comp实例有两种途径：单态工厂模式和Ioc。</p>
		<p>工厂模式实现如下：</p>
		<table bordercolor="#cccccc" cellspacing="2" cellpadding="2" width="87%" bgcolor="#cccccc" border="0">
				<tbody>
						<tr>
								<td>
										<p>public class B{<br />　　 private C comp; <br />　　private final static MyFactory myFactory = MyFactory.getInstance();</p>
										<p>　　public B(){<br />　　　　this.comp = myFactory.createInstanceOfC();</p>
										<p>　　}<br />　　 public void someMethod(){<br />　　　　this.comp.sayHello();<br />　 } <br />　　......<br />} </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>特点：</p>
		<ul>
				<li>每次运行时，MyFactory可根据配置文件XML中定义的C子类实现，通过createInstanceOfC()生成C的具体实例。 </li>
		</ul>
		<p>使用Ioc依赖性注射( Dependency Injection )实现Picocontainer如下，B类如同通常POJO类，如下：</p>
		<table bordercolor="#cccccc" cellspacing="2" cellpadding="2" width="87%" bgcolor="#cccccc" border="0">
				<tbody>
						<tr>
								<td>
										<p>public class B{<br />　　 private C comp; <br />　　public B(C comp){<br />　　　　this.comp = comp;<br />　　 }<br />　　 public void someMethod(){<br />　　　　this.comp.sayHello();<br />　　 }<br />　　......<br />} </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>假设C接口/类有有一个具体实现CImp类。当客户端调用B时，使用下列代码：</p>
		<table bordercolor="#cccccc" cellspacing="2" cellpadding="2" width="87%" bgcolor="#cccccc" border="0">
				<tbody>
						<tr>
								<td>
										<p>public class client{<br />　　 public static void main( String[] args ) {<br />　　　　DefaultPicoContainer container = new DefaultPicoContainer();<br />　　　　container.registerComponentImplementation(CImp.class);<br />　　　　container.registerComponentImplementation(B.class);<br />　　　　B b = (B) container.getComponentInstance(B.class);<br />　　　　b.someMethod();<br />　　 }<br />} </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>　　因此，当客户端调用B时，分别使用工厂模式和Ioc有不同的特点和区别：</p>
		<p>　　主要区别体现在B类的代码，如果使用Ioc，在B类代码中将不需要嵌入任何工厂模式等的代码，因为这些工厂模式其实还是与C有些间接的联系，这样，使用Ioc彻底解耦了B和C之间的联系。</p>
		<p>　　使用Ioc带来的代价是：需要在客户端或其它某处进行B和C之间联系的组装。</p>
		<p>　　所以，Ioc并没有消除B和C之间这样的联系，只是转移了这种联系。<br />　　这种联系转移实际也是一种分离关注，它的影响巨大，它提供了AOP实现的可能。</p>
		<h4>Ioc和AOP</h4>
		<p>　　AOP我们已经知道是一种面向切面的编程方式，由于Ioc解放自由了B类，而且可以向B类实现注射C类具体实现，如果把B类想像成运行时的横向动作，无疑注入C类子类就是AOP中的一种Advice，如下图：</p>
		<p>
				<img height="258" src="http://www.jdon.com/AOPdesign/images/aopIoc.png" width="250" />
		</p>
		<p>　　通过下列代码说明如何使用Picocontainer实现AOP，该例程主要实现是记录logger功能，通过Picocontainer可以使用简单一行，使所有的应用类的记录功能激活。</p>
		<p>首先编制一个记录接口：</p>
		<table cellspacing="2" cellpadding="2" width="100%" bgcolor="#cccccc" border="0">
				<tbody>
						<tr bgcolor="#cccccc">
								<td>
										<p>public interface Logging {</p>
										<p>　　public void enableLogging(Log log);</p>
										<p>}</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>有一个LogSwitcher类，主要用来激活具体应用中的记录功能：</p>
		<table cellspacing="2" cellpadding="2" width="100%" bgcolor="#cccccc" border="0">
				<tbody>
						<tr>
								<td>import org.apache.commons.logging.Log;<br />public class LogSwitcher<br />{<br />　 protected Log m_log;<br />　 public void enableLogging(Log log) {<br />　　　　m_log = log;<br />　　　　m_log.info("Logging Enabled");<br />　　}<br />}</td>
						</tr>
				</tbody>
		</table>
		<p>一般的普通应用JavaBeans都可以继承这个类，假设PicoUserManager是一个用户管理类，代码如下：</p>
		<table cellspacing="2" cellpadding="2" width="100%" bgcolor="#cccccc" border="0">
				<tbody>
						<tr>
								<td>public class PicoUserManager extends LogSwitcher<br />{ 
<p>　　..... //用户管理功能<br />}<br />public class PicoXXXX1Manager extends LogSwitcher<br />{ </p><p>　　..... //业务功能<br />}<br />public class PicoXXXX2Manager extends LogSwitcher<br />{ </p><p>　　..... //业务功能<br />}</p></td>
						</tr>
				</tbody>
		</table>
		<p>注意LogSwitcher中Log实例是由外界赋予的，也就是说即将被外界注射进入，下面看看使用Picocontainer是如何注射Log的具体实例的。</p>
		<table cellspacing="2" cellpadding="2" width="100%" bgcolor="#cccccc" border="0">
				<tbody>
						<tr>
								<td>
										<p>
												<br />DefaultPicoContainer container = new DefaultPicoContainer();<br />container.registerComponentImplementation(PicoUserManager.class);<br />container.registerComponentImplementation(PicoXXXX1Manager.class); <br />container.registerComponentImplementation(PicoXXXX2Manager.class);<br />..... </p>
										<p>Logging logging = (Logging) container.getComponentMulticaster();<br /><br />logging.enableLogging(new SimpleLog("pico"));//激活log<br /><br /></p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>　　由上代码可见，通过使用简单一行logging.enableLogging()方法使所有的应用类的记录功能激活。这是不是类似AOP的advice实现？</p>
		<p>　　总之，使用Ioc模式，可以不管将来具体实现，完全在一个抽象层次进行描述和技术架构，因此，Ioc模式可以为容器、框架之类的软件实现提供了具体的实现手段，属于架构技术中一种重要的模式应用。J道的<a href="http://www.jdon.com/product.htm" target="_blank">JdonSD框架</a>也使用了Ioc模式。</p>
<img src ="http://www.blogjava.net/ocean07000814/aggbug/70689.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ocean07000814/" target="_blank">非洲小白脸</a> 2006-09-20 09:30 <a href="http://www.blogjava.net/ocean07000814/articles/70689.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>