<?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>MoDoFo.println(" &#187; spring</title>
	<atom:link href="http://zhangv.com/archives/tag/spring/feed" rel="self" type="application/rss+xml" />
	<link>http://zhangv.com</link>
	<description>Life for Idea - forever young</description>
	<lastBuildDate>Sat, 07 Apr 2012 04:08:37 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>使用AOP处理事务重试</title>
		<link>http://zhangv.com/archives/1537</link>
		<comments>http://zhangv.com/archives/1537#comments</comments>
		<pubDate>Fri, 09 Jul 2010 11:16:00 +0000</pubDate>
		<dc:creator>zhangv</dc:creator>
				<category><![CDATA[非技术(non-tech)]]></category>
		<category><![CDATA[AOP]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://zhangv.com/archives/1537</guid>
		<description><![CDATA[以下摘自&#60;pojo in action&#62;备查. 算是比较有用的东西,以后可能用到.
Using an AOP interceptor to retry transactionsA Spring application can use a custom AOP interceptor to catch the Concurrency-FailureException and automatically retry the transaction. Here is a customSpring AOP interceptor that does this:public class TransactionRetryInterceptorimplements MethodInterceptor {protected int maxRetryCount = 3;public void setMaxRetryCount(int maxRetryCount) {this.maxRetryCount = maxRetryCount;}public Object invoke(MethodInvocation invocation)throws Throwable {int [...]]]></description>
			<content:encoded><![CDATA[<p>以下摘自&lt;pojo in action&gt;备查. 算是比较有用的东西,以后可能用到.</p>
<p>Using an AOP interceptor to retry transactions<br />A Spring application can use a custom AOP interceptor to catch the Concurrency-<br />FailureException and automatically retry the transaction. Here is a custom<br />Spring AOP interceptor that does this:<br />public class TransactionRetryInterceptor<br />implements MethodInterceptor {<br />protected int maxRetryCount = 3;<br />public void setMaxRetryCount(int maxRetryCount) {<br />this.maxRetryCount = maxRetryCount;<br />}<br />public Object invoke(MethodInvocation invocation)<br />throws Throwable {<br />int retryCount = 0;<br />while (true)<br />try {<br />ReflectiveMethodInvocation inv =<br />(ReflectiveMethodInvocation) invocation;<br />MethodInvocation anotherInvocation = inv.invocableClone();<br />return anotherInvocation.proceed();<br />} catch (ConcurrencyFailureException e) {<br />if (retryCount++ &gt; maxRetryCount)<br />throw e;<br />else {<br />continue;<br />}<br />}<br />}<br />}<br />This class has a maxRetryCount property whose default value is 3. The invoke()<br />method catches the ConcurrencyFailureException and loops at most maxRetry-<br />Count times, retrying the transaction. Because proceed() can only be called once,<br />invoke() clones the MethodInvocation before calling it. The TransactionRetry-<br />Interceptor is a good example of the power and flexibility of the Spring framework.</p>

	Tags: <a href="http://zhangv.com/archives/tag/aop" title="AOP" rel="tag">AOP</a>, <a href="http://zhangv.com/archives/tag/spring" title="spring" rel="tag">spring</a><br />
]]></content:encoded>
			<wfw:commentRss>http://zhangv.com/archives/1537/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>mindmap &#8211; spring事务配置</title>
		<link>http://zhangv.com/archives/1231</link>
		<comments>http://zhangv.com/archives/1231#comments</comments>
		<pubDate>Sun, 23 Aug 2009 12:43:00 +0000</pubDate>
		<dc:creator>zhangv</dc:creator>
				<category><![CDATA[技术(Tech)]]></category>
		<category><![CDATA[mindmap]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[事务]]></category>

		<guid isPermaLink="false">http://zhangv.com/archives/1231</guid>
		<description><![CDATA[


	Tags: mindmap, spring, 事务
]]></description>
			<content:encoded><![CDATA[<p><img style="max-width: 800px;" src="http://zhangv.com/wordpress/wp-content/uploads/spring-transaction-management.png" /></p>
<div class="zemanta-pixie"><img class="zemanta-pixie-img" alt="" src="http://img.zemanta.com/pixy.gif?x-id=64fccc11-8dfc-8278-a8a6-13e4353ffab0" /></div>

	Tags: <a href="http://zhangv.com/archives/tag/mindmap" title="mindmap" rel="tag">mindmap</a>, <a href="http://zhangv.com/archives/tag/spring" title="spring" rel="tag">spring</a>, <a href="http://zhangv.com/archives/tag/%e4%ba%8b%e5%8a%a1" title="事务" rel="tag">事务</a><br />
]]></content:encoded>
			<wfw:commentRss>http://zhangv.com/archives/1231/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SimpleFormController的流程图</title>
		<link>http://zhangv.com/archives/356</link>
		<comments>http://zhangv.com/archives/356#comments</comments>
		<pubDate>Sat, 07 Jun 2008 08:29:39 +0000</pubDate>
		<dc:creator>zhangv</dc:creator>
				<category><![CDATA[技术(Tech)]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://zhangv.com/?p=356</guid>
		<description><![CDATA[
放到这里留作备份.还有一个pdf版的更详细.

	Tags: Java, spring
]]></description>
			<content:encoded><![CDATA[<p><a href="http://zhangv.com/wordpress/wp-content/uploads/spring-form-controller-flow.jpg"><img class="alignnone size-medium wp-image-355" title="spring-form-controller-flow" src="http://zhangv.com/wordpress/wp-content/uploads/spring-form-controller-flow-227x300.jpg" alt="" width="227" height="300" /></a></p>
<p>放到这里留作备份.还有一个<a href="http://www.google.com.hk/url?sa=t&amp;ct=res&amp;cd=3&amp;url=http%3A%2F%2Fhome.exetel.com.au%2Fcweatures%2Fdev%2FSimpleFormControllerCheatSheet_1.2.pdf&amp;ei=WCRWSLW2JYqw6wOW8YWIAw&amp;usg=AFQjCNEVXOQLY7vq4K2Ti1FBfZ1l1uk3TQ&amp;sig2=0zfdDzkj-xAisiWrr-dkDQ">pdf版</a>的更详细.</p>

	Tags: <a href="http://zhangv.com/archives/tag/java" title="Java" rel="tag">Java</a>, <a href="http://zhangv.com/archives/tag/spring" title="spring" rel="tag">spring</a><br />
]]></content:encoded>
			<wfw:commentRss>http://zhangv.com/archives/356/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>spring的tip</title>
		<link>http://zhangv.com/archives/307</link>
		<comments>http://zhangv.com/archives/307#comments</comments>
		<pubDate>Wed, 28 May 2008 08:28:47 +0000</pubDate>
		<dc:creator>zhangv</dc:creator>
				<category><![CDATA[技术(Tech)]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://zhangv.com/archives/307</guid>
		<description><![CDATA[发现用spring有一个问题,如果某个人忘记加入一个类文件,而这个依赖是在spring中体现的,那么在编译时不会报错, 而显然是不好的.这种错误应该在编译的时候就应该报出来. 考虑在编译时检查一次bean依赖, 最简单就是初始化一次application-context.

	Tags: spring, tips
]]></description>
			<content:encoded><![CDATA[<p>发现用spring有一个问题,如果某个人忘记加入一个类文件,而这个依赖是在spring中体现的,那么在编译时不会报错, 而显然是不好的.这种错误应该在编译的时候就应该报出来. 考虑在编译时检查一次bean依赖, 最简单就是初始化一次application-context.</p>

	Tags: <a href="http://zhangv.com/archives/tag/spring" title="spring" rel="tag">spring</a>, <a href="http://zhangv.com/archives/tag/tips" title="tips" rel="tag">tips</a><br />
]]></content:encoded>
			<wfw:commentRss>http://zhangv.com/archives/307/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Spring SimpleFormController Cheatsheet</title>
		<link>http://zhangv.com/archives/128</link>
		<comments>http://zhangv.com/archives/128#comments</comments>
		<pubDate>Sun, 10 Feb 2008 10:45:28 +0000</pubDate>
		<dc:creator>zhangv</dc:creator>
				<category><![CDATA[技术(Tech)]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[开发]]></category>

		<guid isPermaLink="false">http://218.22.170.60/zhangv/wordpress/?p=174</guid>
		<description><![CDATA[pdf下载 

	Tags: spring, 开发
]]></description>
			<content:encoded><![CDATA[<p><a href="http://218.22.170.60/zhangv/wordpress/wp-content/uploads/simpleformcontrollercheatsheet_12.pdf">pdf下载 </a></p>

	Tags: <a href="http://zhangv.com/archives/tag/spring" title="spring" rel="tag">spring</a>, <a href="http://zhangv.com/archives/tag/%e5%bc%80%e5%8f%91" title="开发" rel="tag">开发</a><br />
]]></content:encoded>
			<wfw:commentRss>http://zhangv.com/archives/128/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>acegi整合struts-menu时filter-mapping的问题</title>
		<link>http://zhangv.com/archives/124</link>
		<comments>http://zhangv.com/archives/124#comments</comments>
		<pubDate>Mon, 04 Feb 2008 06:54:28 +0000</pubDate>
		<dc:creator>zhangv</dc:creator>
				<category><![CDATA[技术(Tech)]]></category>
		<category><![CDATA[acegi]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[struts-menu]]></category>

		<guid isPermaLink="false">http://218.22.170.60/zhangv/wordpress/?p=172</guid>
		<description><![CDATA[今天在整合acegi和struts-menu的时候老是有问题,跟进源代码发现struts-menu的RolesPermissionsAdapter 中:
public boolean isAllowed(MenuComponent menu) {
if (menu.getRoles() == null) {
return true; // no roles define, allow everyone
} else {
// Get the list of roles this menu allows
String[] allowedRoles = delimiters.split(menu.getRoles());
for (int i=0; i &#60; allowedRoles.length; i++) {
if (request.isUserInRole(allowedRoles[i])) {
return true;
}
}
}
return false;
}
request.isUserInRole(allowedRoles[i])返回是false. - 因为这个request是sitemesh的pageinforequestWrapper!!!
(之前找了各种可能都没有发现异常,试了无数种 可能的原因)
为什么会这样,之前做的也是完全一样啊?仔细比较了以前写的和现在的,发现 filter-mapping的顺序不一样:
之前写的是acegi的filter-mapping在第一个,试着把现在的filtermapping 放到第一个.成功!
原来filter-mapping的顺序也是有讲究的.如果先mapping sitemesh的filter,request就会被sitemesh的pageinforequestwrapper(?) 包裹,然后就不能被acegi的filter包装成SecurityContextHolderAwareRequestWrapper.
这样在调用isUserInRole时候就出问题了,因为使用的不是acegi的实现.
记录下来.

	Tags: acegi, spring, struts-menu
]]></description>
			<content:encoded><![CDATA[<p>今天在整合acegi和struts-menu的时候老是有问题,跟进源代码发现struts-menu的RolesPermissionsAdapter 中:</p>
<p>public boolean isAllowed(MenuComponent menu) {<br />
if (menu.getRoles() == null) {<br />
return true; // no roles define, allow everyone<br />
} else {<br />
// Get the list of roles this menu allows<br />
String[] allowedRoles = delimiters.split(menu.getRoles());<br />
for (int i=0; i &lt; allowedRoles.length; i++) {<br />
if (<strong>request.isUserInRole(allowedRoles[i])</strong>) {<br />
return true;<br />
}<br />
}<br />
}<br />
return false;<br />
}</p>
<p><strong>request.isUserInRole(allowedRoles[i])返回是false. - 因为这个request是sitemesh的pageinforequestWrapper!!!</strong><br />
(之前找了各种可能都没有发现异常,试了无数种 可能的原因)</p>
<p>为什么会这样,之前做的也是完全一样啊?仔细比较了以前写的和现在的,发现 filter-mapping的顺序不一样:</p>
<p>之前写的是acegi的filter-mapping在第一个,试着把现在的filtermapping 放到第一个.成功!</p>
<p>原来filter-mapping的顺序也是有讲究的.如果先mapping sitemesh的filter,request就会被sitemesh的pageinforequestwrapper(?) 包裹,然后就不能被acegi的filter包装成SecurityContextHolderAwareRequestWrapper.</p>
<p>这样在调用isUserInRole时候就出问题了,因为使用的不是acegi的实现.</p>
<p>记录下来.</p>

	Tags: <a href="http://zhangv.com/archives/tag/acegi" title="acegi" rel="tag">acegi</a>, <a href="http://zhangv.com/archives/tag/spring" title="spring" rel="tag">spring</a>, <a href="http://zhangv.com/archives/tag/struts-menu" title="struts-menu" rel="tag">struts-menu</a><br />
]]></content:encoded>
			<wfw:commentRss>http://zhangv.com/archives/124/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SpringIDE的误导</title>
		<link>http://zhangv.com/archives/98</link>
		<comments>http://zhangv.com/archives/98#comments</comments>
		<pubDate>Fri, 11 Jan 2008 07:10:30 +0000</pubDate>
		<dc:creator>zhangv</dc:creator>
				<category><![CDATA[非技术(non-tech)]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[源码研究]]></category>

		<guid isPermaLink="false">http://218.22.170.60/zhangv/wordpress/?p=105</guid>
		<description><![CDATA[用springide验证了一下xml文件,得到这个错误
Destroy-method 'shutdown' not found in bean class 'org.enhydra.jdbc.pool.StandardXAPoolDataSource'
bean的配置如下:
 也就是说springide认为这个bean没有shutdown的方法.查了一下xapool的source,发现是有的,但是是shutdown(boolean).destroy-method属性的定义:
Attribute : destroy-method
The name of the custom destroy method to invoke on bean factory shutdown. The method must
have no arguments, but may throw any exception. Note: Only invoked on beans whose lifecycle is
under the full control of the factory - which is always the case for singletons, [...]]]></description>
			<content:encoded><![CDATA[<p>用springide验证了一下xml文件,得到这个错误</p>
<p>Destroy-method 'shutdown' not found in bean class 'org.enhydra.jdbc.pool.StandardXAPoolDataSource'</p>
<p>bean的配置如下:</p>
<p> 也就是说springide认为这个bean没有shutdown的方法.查了一下xapool的source,发现是有的,但是是shutdown(boolean).destroy-method属性的定义:</p>
<p>Attribute : destroy-method<br />
The name of the custom destroy method to invoke on bean factory shutdown. The method must<br />
have no arguments, but may throw any exception. Note: Only invoked on beans whose lifecycle is<br />
under the full control of the factory - which is always the case for singletons, but not guaranteed<br />
for any other scope.</p>
<p>在来看spring的source终于发现玄机所在:</p>
<p>DisposableBeanAdapter的invokeCustomDestroyMethod 方法:</p>
<p><code>Class[] paramTypes = destroyMethod.getParameterTypes();<br />
if (paramTypes.length &gt; 1) {<br />
logger.error("Method '" + destroyMethodName + "' of bean '" + this.beanName +<br />
"' has more than one parameter - not supported as destroy method");<br />
}<br />
else if (<font color="#ff0000">paramTypes.length == 1 &amp;&amp; !paramTypes[0].equals(boolean.class)</font>) {<br />
logger.error("Method '" + destroyMethodName + "' of bean '" + this.beanName +<br />
"' has a non-boolean parameter - not supported as destroy method");<br />
}<br />
else {<br />
Object[] args = new Object[paramTypes.length];<br />
<font color="#ff0000">  if (paramTypes.length == 1) {<br />
args[0] = Boolean.TRUE;<br />
}</font><br />
if (!Modifier.isPublic(destroyMethod.getModifiers()) ||<br />
!Modifier.isPublic(destroyMethod.getDeclaringClass().getModifiers())) {<br />
destroyMethod.setAccessible(true);<br />
}<br />
</code><br />
红色标记的地方就看到了,这个方法只会接受一个无参数方法或者参数唯一并且是boolean的方法.boolean值得意义就是force</p>
<p>附方法的注释:<br />
This implementation invokes a no-arg method if found, else checking<br />
for a method with a single boolean argument (passing in "true",<br />
assuming a "force" parameter), else logging an error.</p>
<p>显然SpringIDE没有考虑到这点.</p>

	Tags: <a href="http://zhangv.com/archives/tag/spring" title="spring" rel="tag">spring</a>, <a href="http://zhangv.com/archives/tag/%e6%ba%90%e7%a0%81%e7%a0%94%e7%a9%b6" title="源码研究" rel="tag">源码研究</a><br />
]]></content:encoded>
			<wfw:commentRss>http://zhangv.com/archives/98/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Spring的FactoryBean和InitializingBean</title>
		<link>http://zhangv.com/archives/75</link>
		<comments>http://zhangv.com/archives/75#comments</comments>
		<pubDate>Thu, 13 Dec 2007 02:33:20 +0000</pubDate>
		<dc:creator>zhangv</dc:creator>
				<category><![CDATA[技术(Tech)]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://218.22.170.60/zhangv/wordpress/?p=88</guid>
		<description><![CDATA[刚刚“领略”了一些spring-modules的源代码看到了FactoryBean和InitiliazingBean的用处。记在这里

InitializingBean.afterPropertiesSet()

这个方法比较容易理解，是在spring根据配置文件设置了bean的属性后调用的，一般这里会做一些初始化的工作。比如，xml配置中只是提供了resource的路径，在这个方法里 就要根据resource的路径初始化一些成员变量（那些不能被注入或者没有被注入的成员变量）。
public void afterPropertiesSet() throws Exception {
if (this.definitionLocation == null) {
throw new FatalBeanException("Property [definitionLocation] of class ["
+ ProcessDefinitionFactoryBean.class.getName()
+ "] is required.");
}
InputStream inputStream = null;
try {
inputStream = this.definitionLocation.getInputStream();
this.processDefinition = ProcessDefinition.parseXmlInputStream(inputStream);
//        这里就是初始化的地方，spring的配置文件中只配置了definitionLocation的信息，其他的事就在这里做
}
finally {
if (inputStream != null) {
inputStream.close();
}
}
}

FactoryBean.getObject &#38; getObjectType

在比较配置文件和源代码的时候我很疑惑，为什么类型都不对头，怎么可以注入的？答案就在FactoryBean的这两个方法里
public Object getObject() throws Exception {
return this.processDefinition;
}
public Class getObjectType() {
return (processDefinition == null) ? ProcessDefinition.class : [...]]]></description>
			<content:encoded><![CDATA[<p>刚刚“领略”了一些spring-modules的源代码看到了FactoryBean和InitiliazingBean的用处。记在这里</p>
<ul>
<li>InitializingBean.afterPropertiesSet()</li>
</ul>
<p>这个方法比较容易理解，是在spring根据配置文件设置了bean的属性后调用的，一般这里会做一些初始化的工作。比如，xml配置中只是提供了resource的路径，在这个方法里 就要根据resource的路径初始化一些成员变量（那些不能被注入或者没有被注入的成员变量）。</p>
<p>public void afterPropertiesSet() throws Exception {<br />
if (this.definitionLocation == null) {<br />
throw new FatalBeanException("Property [definitionLocation] of class ["<br />
+ ProcessDefinitionFactoryBean.class.getName()<br />
+ "] is required.");<br />
}</p>
<p>InputStream inputStream = null;<br />
try {<br />
inputStream = this.definitionLocation.getInputStream();<br />
<strong>this.processDefinition = ProcessDefinition.parseXmlInputStream(inputStream);</strong><br />
//        这里就是初始化的地方，spring的配置文件中只配置了definitionLocation的信息，其他的事就在这里做</p>
<p>}<br />
finally {<br />
if (inputStream != null) {<br />
inputStream.close();<br />
}<br />
}<br />
}</p>
<ul>
<li>FactoryBean.getObject &amp; getObjectType</li>
</ul>
<p>在比较配置文件和源代码的时候我很疑惑，为什么类型都不对头，怎么可以注入的？答案就在FactoryBean的这两个方法里</p>
<p>public Object getObject() throws Exception {<br />
return this.processDefinition;<br />
}</p>
<p>public Class getObjectType() {<br />
return (processDefinition == null) ? ProcessDefinition.class : processDefinition.getClass();<br />
}</p>
<p>getObject返回的是成员变量processDefinition，getObjectType返回的也不是this.class，而是processDefinition.getClass()；spring在加载这样的factorybean的时候就会根据这两个方法来决定类型和实例。比如在xml中配置了ref="someFactoryBean"的 时候，实际的引用可以是任意的，只要你提供了这两个方法。-好像有点表达不清楚。</p>

	Tags: <a href="http://zhangv.com/archives/tag/java" title="Java" rel="tag">Java</a>, <a href="http://zhangv.com/archives/tag/spring" title="spring" rel="tag">spring</a><br />
]]></content:encoded>
			<wfw:commentRss>http://zhangv.com/archives/75/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AOP也是注入?</title>
		<link>http://zhangv.com/archives/45</link>
		<comments>http://zhangv.com/archives/45#comments</comments>
		<pubDate>Fri, 23 Nov 2007 03:12:44 +0000</pubDate>
		<dc:creator>zhangv</dc:creator>
				<category><![CDATA[技术(Tech)]]></category>
		<category><![CDATA[AOP]]></category>
		<category><![CDATA[IOC]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://218.22.170.60/zhangv/wordpress/?p=51</guid>
		<description><![CDATA[如果IOC是运行时对象依赖关系的注入的话,那么AOP是不是就是运行期执行流的注入呢?
每个注入点(point cut)就对应IOC中的sette或构造函数参数.每个处理方法(advice)就对应IOC中的一个对象

	Tags: AOP, IOC, spring
]]></description>
			<content:encoded><![CDATA[<p>如果IOC是运行时对象依赖关系的注入的话,那么AOP是不是就是运行期执行流的注入呢?</p>
<p>每个注入点(point cut)就对应IOC中的sette或构造函数参数.每个处理方法(advice)就对应IOC中的一个对象</p>

	Tags: <a href="http://zhangv.com/archives/tag/aop" title="AOP" rel="tag">AOP</a>, <a href="http://zhangv.com/archives/tag/ioc" title="IOC" rel="tag">IOC</a>, <a href="http://zhangv.com/archives/tag/spring" title="spring" rel="tag">spring</a><br />
]]></content:encoded>
			<wfw:commentRss>http://zhangv.com/archives/45/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>啥是Spring</title>
		<link>http://zhangv.com/archives/26</link>
		<comments>http://zhangv.com/archives/26#comments</comments>
		<pubDate>Fri, 02 Nov 2007 13:39:29 +0000</pubDate>
		<dc:creator>zhangv</dc:creator>
				<category><![CDATA[技术(Tech)]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://218.22.170.60/zhangv/wordpress/2007/11/02/%e5%95%a5%e6%98%afspring/</guid>
		<description><![CDATA[(最初发布在JavaResearch.org,现在整理好放到自己的地方.)
有人说spring aop+ spring ioc, 才~~~是spring
简单一点,是一个容器. 什么容器,容纳什么?是对象,或者说bean的容器.
那为什么叫轻量级容器呢?相对于EJB container,使用spring不需要写符合容器规范的代码,即容器不会"侵入"了你的代码.
这 个容器会提供你的应用(程序)中用到的所有对象,并对这些对象进行统一的生命周期管理和组装.在通常的开发中,我们在需要某个对象的时候只是  new MyObject(). 在Java中,这样没有什么不好,因为gc会打理好"善后"工作,是系统级的. 而用spring,在需要某个对象 时,只要向容器请求相应的对象,spring会找到并准备好这些对象并提供给你.她也会打理好"善后"工作,但是是在应用级的.
另一方面,spring还会帮助你打理对象之间的依赖关系.
比如原来的做法:
class A{
}
class B{
A a ;
public B(){ a = new A();}
}
而使用spring的做法
class A{
}
class B{
A a;
public B(){}
void setA(A a){this.a=a}
A getA(){return this.a}
}
(希望你不要单纯地认为spring会写很多代码)
但 从前一个方面,你可能觉得spring只是一个对象容器.从这里你就应该看出,spring是bean容器,因为spring需要你的类符合bean规 范:相应于每一个成员域,都需要提供setter和getter方法.spring要使用这些方法来注入依赖关系,也就是  dependence injection, 或者inversion of control. 我个人觉得还是di更容易理解,直到现在我还是要考虑 怎么去向别人很好的解释ioc.控制反转(倒转),我的理解是就如同上面的两个例子里看到的,依赖(控制)不在体现在代码逻辑里(如第一个例子),而是在 配置文件里,而在代码中我们只提供注入点(也就是setter和getter).
希望我对IoC的概念的讲解能够给你一些启发.
你 可能要问了,为什么我要这样做呢?原来的做法有什么不妥的地方么?没有什么不妥,只是两种理念而已,没有绝对的好还是不好,但我还是给你我的解释--我理 解的IoC的好处,希望有所帮助.通常在程序设计的时候,我们在需要某些功能时,会相应的去设计一些方法,然后根据OO去将方法和一成员变量组成一个类. 实际上,我们最终设计出的程序是:一组类的实例互相交互完成某个特定的任务.
除了一些核心的业务方法,以外我们还要做组装对象的工作.比如我有了 一个工厂,里面有很多机器,机器在开动时要装配相应的模具.那么在工厂的生产过程中, 首先我要有工厂,机器,模具这样三个类.然后我的"动作"有:装 配,开机.通常的做法我们要做装配,然后再去开机.而用spring,我们只是专注于开机.这样我们就把装配这个动作抽离出了核心的"生产过程".当某些 机器改变了装配模具时,不在需要修改核心业务代码.这就是解耦.如:
public class Production{
public static void main(String[] args){
Factory [...]]]></description>
			<content:encoded><![CDATA[<p>(最初发布在<a href="http://javaresearch.org/article/56242.htm">JavaResearch.org</a>,现在整理好放到自己的地方.)</p>
<p>有人说spring aop+ spring ioc, 才~~~是spring<br />
简单一点,是一个容器. 什么容器,容纳什么?是对象,或者说bean的容器.<br />
那为什么叫轻量级容器呢?相对于EJB container,使用spring不需要写符合容器规范的代码,即容器不会"侵入"了你的代码.</p>
<p>这 个容器会提供你的应用(程序)中用到的所有对象,并对这些对象进行统一的生命周期管理和组装.在通常的开发中,我们在需要某个对象的时候只是  new MyObject(). 在Java中,这样没有什么不好,因为gc会打理好"善后"工作,是系统级的. 而用spring,在需要某个对象 时,只要向容器请求相应的对象,spring会找到并准备好这些对象并提供给你.她也会打理好"善后"工作,但是是在应用级的.<br />
另一方面,spring还会帮助你打理对象之间的依赖关系.<br />
比如原来的做法:</p>
<p>class A{<br />
}<br />
class B{<br />
A a ;<br />
public B(){ a = new A();}<br />
}</p>
<p>而使用spring的做法<br />
class A{<br />
}<br />
class B{<br />
A a;<br />
public B(){}<br />
void setA(A a){this.a=a}<br />
A getA(){return this.a}<br />
}<br />
(希望你不要单纯地认为spring会写很多代码)<br />
但 从前一个方面,你可能觉得spring只是一个对象容器.从这里你就应该看出,spring是bean容器,因为spring需要你的类符合bean规 范:相应于每一个成员域,都需要提供setter和getter方法.spring要使用这些方法来注入依赖关系,也就是  dependence injection, 或者inversion of control. 我个人觉得还是di更容易理解,直到现在我还是要考虑 怎么去向别人很好的解释ioc.控制反转(倒转),我的理解是就如同上面的两个例子里看到的,依赖(控制)不在体现在代码逻辑里(如第一个例子),而是在 配置文件里,而在代码中我们只提供注入点(也就是setter和getter).</p>
<p>希望我对IoC的概念的讲解能够给你一些启发.<br />
你 可能要问了,为什么我要这样做呢?原来的做法有什么不妥的地方么?没有什么不妥,只是两种理念而已,没有绝对的好还是不好,但我还是给你我的解释--我理 解的IoC的好处,希望有所帮助.通常在程序设计的时候,我们在需要某些功能时,会相应的去设计一些方法,然后根据OO去将方法和一成员变量组成一个类. 实际上,我们最终设计出的程序是:一组类的实例互相交互完成某个特定的任务.<br />
除了一些核心的业务方法,以外我们还要做组装对象的工作.比如我有了 一个工厂,里面有很多机器,机器在开动时要装配相应的模具.那么在工厂的生产过程中, 首先我要有工厂,机器,模具这样三个类.然后我的"动作"有:装 配,开机.通常的做法我们要做装配,然后再去开机.而用spring,我们只是专注于开机.这样我们就把装配这个动作抽离出了核心的"生产过程".当某些 机器改变了装配模具时,不在需要修改核心业务代码.这就是解耦.如:</p>
<p>public class Production{<br />
public static void main(String[] args){<br />
Factory factory = (Factory)BeanFactory.getBean("factory");<br />
factory.launchProduction();<br />
}<br />
}</p>
<p>class Factory{<br />
Machine machine1,machine2;<br />
void launchProduction(){<br />
machine1.start(); machine2.start();<br />
}<br />
// setters and getters<br />
}</p>
<p>class Machine{<br />
Tool tool;<br />
void start(){<br />
}<br />
// setters and getters<br />
}</p>
<p>在launchProduction()方法中只需要开动每台机器即可.而不需要每次都装配机器.装配的工作交给了别人.现在只要按下start按钮.生产就开始了!要是原来:</p>
<p>void launchProduction(){<br />
machine1 = new MachineA();<br />
machine1.setTool(new ToolA());<br />
machine2 = new MachineB();<br />
machine2.setTool(new ToolB());<br />
machine1.start();<br />
machine2.start();<br />
}</p>
<p>这就是工作分工,是不是感觉轻松了许多?从此以后,我们都是面向构件去开发,而不需要过多地在代码中体现构件之间的依赖关系.</p>
<p>AOP<br />
推荐你看一下&lt;&lt;effective enterprise java&gt;&gt;的第一章,对AOP有很清晰,易懂的解释.其实AOP并非很艰深晦涩的概念,但是从架构角度去理解她的重要性可能不是我这样的new fish一时半会儿可以领悟到的.<br />
我这里只是想说,有些概念你要知道是怎么回事,但理解到多深,除了天赋以外更多的是经验和悟.所以不要心急.--像是在自我解嘲.<br />
也许在不知不觉中你就使用了很多AOP的概念,比如servlet里的filter,比如在写一个command类时,给她的调用类在每次调用command时前后加上:preProcess和postProcess...<br />
我不想解释太多,&lt;&lt;eej&gt;&gt;的解释已经足够.</p>
<p>Hope helps.</p>

	Tags: <a href="http://zhangv.com/archives/tag/java" title="Java" rel="tag">Java</a>, <a href="http://zhangv.com/archives/tag/spring" title="spring" rel="tag">spring</a><br />
]]></content:encoded>
			<wfw:commentRss>http://zhangv.com/archives/26/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

