??xml version="1.0" encoding="utf-8" standalone="yes"?>精品久久久久久亚洲综合网,亚洲乱码国产一区网址,亚洲熟妇av一区二区三区下载http://www.tkk7.com/liulu/category/15186.htmlOpen & Open <a title="Free Web Counter"><font color="red"><script src="http://fastwebcounter.com/secure.php?s=www.tkk7.com/liulu"></script>hits</font></a>zh-cnFri, 02 Mar 2007 02:39:13 GMTFri, 02 Mar 2007 02:39:13 GMT60《Pro Spring》学?fn)笔?9)Q-基础q阶(4)http://www.tkk7.com/liulu/archive/2006/12/21/89217.html刘璐刘璐Thu, 21 Dec 2006 02:25:00 GMThttp://www.tkk7.com/liulu/archive/2006/12/21/89217.htmlhttp://www.tkk7.com/liulu/comments/89217.htmlhttp://www.tkk7.com/liulu/archive/2006/12/21/89217.html#Feedback0http://www.tkk7.com/liulu/comments/commentRss/89217.htmlhttp://www.tkk7.com/liulu/services/trackbacks/89217.html (tng)
 (tng) (tng) (tng) (tng) (tng) 到目前ؓ(f)止,我们都是使用BeanFactory接口以及(qing)它的子接口来使用SpringQ尽用BeanFactory也是一U不错的方式Q但正如前面看到的,有些时候,我们q是不得不自q写代码来调用诸如preInstantiateSingletonsQ?font color="#000000">postProcessBeanFactory{方法?/font>
 (tng) (tng) (tng) (tng) (tng) Z(jin)使用的方便,Spring提供?jin)BeanFactory的一个扩展:(x)ApplicationContext。用ApplicationContextQ我们可以减需要编写的代码的数量,q且ApplicationContext也增加了(jin)一些新的功能。如果在Web工程中用SpringQ我们甚臛_以让Spring自动加蝲ApplicationContextQ而无需自己~写代码来创建它?/div>
 (tng) (tng) (tng) (tng) (tng) ApplicationContext具备一些BeanFactory不具备的功能Q国际化QInternationalizationQ,事g发布QEvent publicationQ,资源理和访问(Resource management and accessQ,更多的生命周期控制接口(Additional lifecycle interfacesQ以?qing)底层组件的自动配置QImproved automatic configuration of infrastructure componentsQ?/div>
 (tng) (tng) (tng) (tng) (tng) Spring为ApplicationContext接口提供?jin)三U实玎ͼ(x)FileSystemXmlApplicationContextQClasspathXmlApplicationContext和XmlWebApplicationContext。其中XmlWebApplicationContext是专为Web工程定制的,q且我们可以使用ContextLoaderListener或ContextLoaderServlet来自动加载ApplicationContext配置?/div>
 (tng) (tng) (tng) (tng) (tng) 通常国际化是通过使用MessageSource接口来实现的Qؓ(f)?jin)在ApplicationContext中用MessageSourceQ我们需要配|一个类型ؓ(f)MessageSourceQ名UCؓ(f)messageSource的bean?/div>
<beans>
 (tng) (tng) (tng) <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="basenames">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <list>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>buttons</value>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>labels</value>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) </list>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) </property>
 (tng) (tng) (tng) (tng) </bean>
</beans>
 (tng) (tng) (tng) (tng) (tng) 在配|了(jin)messageSource后,我们可以用ApplicationContext的getMessageҎ(gu)来获取资源内容了(jin)?/div>
 (tng) (tng) (tng) (tng) (tng) ApplicationContext的另一个重要特性就是对发布和接收事件的支持QApplicationContext?x)在其被配置的时候自动注册所有的侦听器(listenerQ,事g的发布是通过ApplicationContext的publishEventҎ(gu)来实现的?/div>
//Event class
public class MessageEvent extends ApplicationEvent {
 (tng) (tng) (tng) private String msg;
 (tng) (tng) (tng) public MessageEvent(Object source, String msg) {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) super(source);
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) this.msg = msg;
 (tng) (tng) (tng) }
 (tng) (tng) (tng) public String getMessage() {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) return msg;
 (tng) (tng) (tng) }
}
//Listener class
public class MessageEventListener implements ApplicationListener {
 (tng) (tng) (tng) public void onApplicationEvent(ApplicationEvent event) {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) if(event instanceof MessageEvent) {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) MessageEvent msgEvt = (MessageEvent)event;
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println("Received: " + msgEvt.getMessage());
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) }
 (tng) (tng) (tng) }
}
//Publish class
public class Publisher implements ApplicationContextAware {
 (tng) (tng) (tng) private ApplicationContext ctx;
 (tng) (tng) (tng) public static void main(String[] args) {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) ApplicationContext ctx =
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) new FileSystemXmlApplicationContext("./ch5/src/conf/events/events.xml");
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) Publisher pub = (Publisher) ctx.getBean("publisher");
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) pub.publish("Hello World!");
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) pub.publish("The quick brown fox jumped over the lazy dog");
 (tng) (tng) (tng) }
 (tng) (tng) (tng) public void setApplicationContext(ApplicationContext applicationContext)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) throws BeansException {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) this.ctx = applicationContext;
 (tng) (tng) (tng) }
 (tng) (tng) (tng) public void publish(String message) {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) ctx.publishEvent(new MessageEvent(this, message));
 (tng) (tng) (tng) }
}
<beans>
 (tng) (tng) (tng) <bean id="publisher" class="com.apress.prospring.ch5.event.Publisher"/>
 (tng) (tng) (tng) <bean id="messageEventListener" class="com.apress.prospring.ch5.event.MessageEventListener"/>
</beans>
 (tng) (tng) (tng) (tng) (tng) 资源讉K是我们经常碰到的Q这些资源有可能存在于一个文件中Q类路径中的一个jar包中Q抑或是在远E服务器上。Spring为我们提供了(jin)l一的,协议无关的方式来讉K各种各样的资源,q给我们讉K各种资源提供?jin)极大的方便?/font>
public class ResourceDemo {
 (tng) (tng) (tng) public static void main(String[] args) throws Exception {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) ApplicationContext ctx =
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) new FileSystemXmlApplicationContext("./ch5/src/conf/events/events.xml");
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) Resource res1 = ctx.getResource("
file:///d:/tmp/test.txt ");
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) displayInfo(res1);
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) Resource res2 = ctx.getResource("classpath:lib/commons-logging.jar");
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) displayInfo(res2);
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) Resource res3 = ctx.getResource("
http://www.google.co.uk ");
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) displayInfo(res3);
 (tng) (tng) (tng) }
 (tng) (tng) (tng) private static void displayInfo(Resource res) throws Exception {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println(res.getClass());
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println(res.getURL().getContent());
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println("");
 (tng) (tng) (tng) }
}


刘璐 2006-12-21 10:25 发表评论
]]>《Pro Spring》学?fn)笔?8)Q-基础q阶(3)http://www.tkk7.com/liulu/archive/2006/12/21/89216.html刘璐刘璐Thu, 21 Dec 2006 02:24:00 GMThttp://www.tkk7.com/liulu/archive/2006/12/21/89216.htmlhttp://www.tkk7.com/liulu/comments/89216.htmlhttp://www.tkk7.com/liulu/archive/2006/12/21/89216.html#Feedback0http://www.tkk7.com/liulu/comments/commentRss/89216.htmlhttp://www.tkk7.com/liulu/services/trackbacks/89216.html (tng)
 (tng) (tng) (tng) (tng) (tng) 如果bean无法单地通过new关键字来创徏怎么办,通常到q样的情冉|Q我们都?x)用工厂模式来处理QSpring也提供了(jin)对FactoryBean的支持,当我们配|了(jin)一个bean为FactoryBeanӞ随后我们获取的则q不是该FactoryBeanQSpring?x)通过调用FactoryBean.getObject()Ҏ(gu)Q返回真正的目标bean。FactoryBean在Spring中的最著名应用是对声明式事务的处理?/div>
 (tng) (tng) (tng) (tng) (tng) 在Spring中用FactoryBeanQ我们需要编写一个实C(jin)FactoryBean接口的类Q以一个信息摘要FactoryBeanZQ它主要实现Ҏ(gu)不同的参敎ͼ创徏不同的MessageDigest的实例?/div>
public class MessageDigestFactoryBean implements FactoryBean, InitializingBean {
 (tng) (tng) (tng) private String algorithmName = "MD5";
 (tng) (tng) (tng) private MessageDigest messageDigest = null;
 (tng) (tng) (tng) public Object getObject() throws Exception {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) return messageDigest.clone();
 (tng) (tng) (tng) }
 (tng) (tng) (tng) public Class getObjectType() {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) return MessageDigest.class;
 (tng) (tng) (tng) }
 (tng) (tng) (tng) public boolean isSingleton() {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) return true;
 (tng) (tng) (tng) }
 (tng) (tng) (tng) public void afterPropertiesSet() throws Exception {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) messageDigest = MessageDigest.getInstance(algorithmName);
 (tng) (tng) (tng) }
 (tng) (tng) (tng) public void setAlgorithmName(String algorithmName) {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) this.algorithmName = algorithmName;
 (tng) (tng) (tng) }
}
 (tng) (tng) (tng) (tng) (tng) getObjectҎ(gu)是供Spring调用Q用来返回真正的beanl其它bean的(而不是FactoryBean本nQ,getObjectTypeҎ(gu)可以q回nullQ但如果指定?jin)类型,可以用Spring的自动装载功能了(jin)。isSingletonҎ(gu)是指定bean是否是单例的Q注意不能通过FactoryBean的配|文件来指定bean是否为单例,因ؓ(f)那样指定的是FactoryBean本nQ而不是真正的目标bean?/font>
 (tng) (tng) (tng) (tng) (tng) FactoryBean的配|和普通beanq没有什么区别?/div>
 (tng) (tng) (tng) (tng) (tng) ׃Bean配置文g中,各个属性都是以String的Ş式配|的Q除?jin)?strong>ref引用其它bean外)(j)Q因此,Spring在组装bean的时候,需要把Stringcd的D{化成合适的cdQ这需要用到JavaBean中的概念Q?strong>PropertyEditor?/div>
 (tng) (tng) (tng) (tng) (tng) Spring内置?U预先注册的PropertyEditorQByteArrayPropertyEditorQClassEditorQFileEditorQLocaleEditorQPropertiesEditorQStringArrayPropertyEditorQURLEditor。通过名字Q我们就能清楚地知道它们对应的类型了(jin)?/div>
 (tng) (tng) (tng) (tng) (tng) 管内置的PropertyEditor可以处理大部分常见的cdQ我们仍然会(x)到需要创qPropertyEditor的情c(din)ؓ(f)?jin)简化自定义PropertyEditor的创建,Spring提供?jin)PropertyEditorSupportc,我们只需要扩展该c,q实现其中的setAsTextҎ(gu)卛_?/div>
public class PatternPropertyEditor extends PropertyEditorSupport {
 (tng) (tng) (tng) public void setAsText(String text) throws IllegalArgumentException {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) Pattern pattern = Pattern.compile(text);
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) setValue(pattern);
 (tng) (tng) (tng) }
}
 (tng) (tng) (tng) (tng) (tng) 可以看到Q实C个自定义的PropertyEditor是很Ҏ(gu)的,但怎么才能让它起作用呢Q也是通常所说的注册PropertyEditor。Spring提供?jin)两U注册的方式Q?.通过ConfigurableBeanFactory的registerCustomEditorҎ(gu)Q?.在BeanFactory的配|文件中定义CustomEditorConfigurer?/font>
<bean name="customEditorConfigurer"
class="org.springframework.beans.factory.config.CustomEditorConfigurer">
 (tng) (tng) (tng) <property name="customEditors">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <map>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <entry key="java.util.regex.Pattern">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <bean class="com.apress.prospring.ch5.pe.PatternPropertyEditor"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) </entry>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) </map>
 (tng) (tng) (tng) </property>
</bean>
 (tng) (tng) (tng) (tng) (tng) 自定义的PropertyEditor是通过CustomEditorConfigurer的一个类型ؓ(f)Map的属性添加的Qkey值是自定义PropertyEditor对应的类型的全类名?/div>
 (tng) (tng) (tng) (tng) (tng) (tng)在用时需要先调用Q?/div>
CustomEditorConfigurer config =
 (tng) (tng) (tng) (CustomEditorConfigurer) factory.getBean("customEditorConfigurer");
config.postProcessBeanFactory(factory);
 (tng) (tng) (tng) (tng) (tng) 来将所有自定义的ProperyEditor注册到BeanFactory中?/div>


刘璐 2006-12-21 10:24 发表评论
]]>《Pro Spring》学?fn)笔?6)Q-基础q阶(1)http://www.tkk7.com/liulu/archive/2006/12/21/89214.html刘璐刘璐Thu, 21 Dec 2006 02:23:00 GMThttp://www.tkk7.com/liulu/archive/2006/12/21/89214.htmlhttp://www.tkk7.com/liulu/comments/89214.htmlhttp://www.tkk7.com/liulu/archive/2006/12/21/89214.html#Feedback0http://www.tkk7.com/liulu/comments/commentRss/89214.htmlhttp://www.tkk7.com/liulu/services/trackbacks/89214.html (tng)
 (tng) (tng) (tng) (tng) (tng) Spring不仅提供?jin)基本的IOC功能Q借助于BeanFactory以及(qing)其它lgQ我们还可以使用其它一些更高的功能。但是需要注意的是,使用q些高功能Q将不可避免的得我们的工程依赖于Spring。这些高U功能大致包括:(x)理bean的生命周期,让bean感知SpringQSpring awareQ,使用Ҏ(gu)注入Q用FactoryBeanQ用PropertyEditor以及(qing)?jin)解Spring的ApplicationContext
 (tng) (tng) (tng) (tng) (tng) (tng)有时候,我们需要在bean的生命周期中的某些阶D做一些相应的操作Q类gServlet和EJBQ,像其它IOC容器一PSpring也提供了(jin)理bean生命周期的功能。两个主要的阶段是:(x)
post-initializationQbean初始化之后)(j)和pre-destructionQbean销毁之前)(j).
 (tng) (tng) (tng) (tng) (tng) post-initialization是指在Spring完成?jin)bean的所有依赖注入以?qing)相应的(g)之后,
 (tng) (tng) (tng) (tng) (tng) pre-destruction是指在Spring销毁bean之前?br /> (tng) (tng) (tng) (tng) (tng) post-initialization和pre-destruction只能应用?strong>sigleton模式的beanQ因为非sigleton的bean的生命周期ƈ不由Spring控制Q它们是由JVM控制的)(j)?br /> (tng) (tng) (tng) (tng) (tng) Spring提供?jin)两U机制来实现bean生命周期的管理:(x)Z接口的和Z指定Ҏ(gu)的?/div>
 (tng) (tng) (tng) (tng) (tng) 使用Z接口的机Ӟ我们需要实现Spring的相x(chng)口,然后QSpring?x)用回调机制在指定的阶D调用接口中定义的方法,从而实现bean生命周期的管理。而用基于指定方法的机制Q我们需要在BeanFactory的配|中指定相应的方法名UͼSpring?x)用Java的反机制在指定的阶D调用我们指定的Ҏ(gu)Q从而实现bean生命周期的管理?br /> (tng) (tng) (tng) (tng) (tng) 选择哪种机制取决于我们的工程的需要。基于接口的机制要求我们实现Spring的接口,q会(x)带来对Spring的依赖,但是当我们定义了(jin)很多相同cd的beanӞ使用Z接口的机制可以免L们ؓ(f)每个bean定义指定相应Ҏ(gu)的麻?ch)。基于指定方法的机制则可以让我们避免对Spring的依赖,q在当我们用第三方的类库(因此Q我们无法修改其代码来实现Spring的接口)(j)时是非常有用的?br /> (tng) (tng) (tng) (tng) (tng) 以post-initializationZQ?br /> (tng) (tng) (tng) (tng) (tng) 使用Z接口的机Ӟ我们需要实现Spring的InitializingBean接口的afterPropertiesSetҎ(gu)
 (tng) (tng) (tng) (tng) (tng) public class SimpleBeanWithInterface implements InitializingBean {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) ...
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) public void afterPropertiesSet() throws Exception {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) ...
 (tng) (tng) (tng) (tng) (tng) (tng) (tng)  (tng) }
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) ...
 (tng) (tng) (tng) (tng) (tng) }
 (tng) (tng) (tng) (tng) (tng) <beans>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <bean id="simpleBean1"
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) class="com.apress.prospring.ch5.lifecycle.SimpleBeanWithInterface">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) ...
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) </bean>
 (tng) (tng) (tng) (tng) (tng) </beans>
 (tng) (tng) (tng) (tng) (tng) 使用Z指定Ҏ(gu)的机Ӟ我们只需在BeanFactory的配|中指定相应的方法名U?br /> (tng) (tng) (tng) (tng) (tng) <beans>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <bean id="simpleBean1"
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) class="com.apress.prospring.ch5.lifecycle.SimpleBean"
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) init-method="init">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) ...
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)</bean>
 (tng) (tng) (tng) (tng) (tng) </beans>

 (tng) (tng) (tng) (tng) (tng) SimpleBean中包含对应的initҎ(gu)
 (tng) (tng) (tng) (tng) (tng) public class SimpleBean {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) ...
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) public void init() {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) ...
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) ...
 (tng) (tng) (tng) (tng) (tng) }

 (tng) (tng) (tng) (tng) (tng) 需要注意的是,initҎ(gu)必须不包含Q何参敎ͼ管我们可以为initҎ(gu)指定L的返回|但Spring?x)忽略它Q因此最好的做法是在initҎ(gu)中抛出异常来表明初始化失败了(jin)?br /> (tng) (tng) (tng) (tng) (tng) 我们也可以同时用这两种机制Q这ӞSpring?x)先调用InitializingBean接口的afterPropertiesSetҎ(gu)Q再调用我们自己指定的initҎ(gu)?br /> (tng) (tng) (tng) (tng) (tng) 相对的,pre-destruction使用DisposableBean接口的destroyҎ(gu)和bean标签的destroy-method属?br /> (tng) (tng) (tng) (tng) (tng) 相对于依赖查找(Dependency LookupQ,依赖注入QDependency InjectionQ最大的卖点是容器的无x(chng),但是有时候,我们实需要和容器q行一些交互,例如讉KBeanFactory或者是获得bean的名U等?br /> (tng) (tng) (tng) (tng) (tng) (tng)Z(jin)获得bean的名Uͼ我们需要实现Spring的BeanNameAware接口QBeanNameAware只有一个方法,void setBeanName(String name)Q只要我们的bean实现?jin)BeanNameAware接口QSpring׃(x)在bean配置l束Q其它生命周期相关的回调函数Qinitialization或?destroyQ调用之前,回调该方法置入bean的名U?/div>
 (tng) (tng) (tng) (tng) (tng) cM的,Z(jin)讉KbeanFactoryQ我们需要实现Spring的BeanFactoryAware接口?/div>
void setBeanFactory(BeanFactory factory)Ҏ(gu)?/div>


刘璐 2006-12-21 10:23 发表评论
]]>《Pro Spring》学?fn)笔?7)Q-基础q阶(2)http://www.tkk7.com/liulu/archive/2006/12/21/89215.html刘璐刘璐Thu, 21 Dec 2006 02:23:00 GMThttp://www.tkk7.com/liulu/archive/2006/12/21/89215.htmlhttp://www.tkk7.com/liulu/comments/89215.htmlhttp://www.tkk7.com/liulu/archive/2006/12/21/89215.html#Feedback0http://www.tkk7.com/liulu/comments/commentRss/89215.htmlhttp://www.tkk7.com/liulu/services/trackbacks/89215.html (tng)
 (tng) (tng) (tng) (tng) (tng) Spring1.1中引入了(jin)一个很有用的IOC新特性-Q方法注入(Method InjectionQ。这能让我们在组装bean时获得极大的灉|性。Spring的方法注入可以分ZUŞ式:(x)查询Ҏ(gu)注入QLookup Method InjectionQ和Ҏ(gu)替换QMethod ReplacementQ。查询方法注入提供了(jin)另一U机制来让bean获取它依赖的其它beanQ方法替换则可以在不修改源代码的基础上,修改Lbean的Q何方法的实现。ؓ(f)?jin)提供这两个功能QSpring借助?jin)CGLIB包?/div>
 (tng) (tng) (tng) (tng) (tng) (tng)先来看看查询Ҏ(gu)注入的用。想象这L(fng)情ŞQ我们有一个singletoncd的bean AQ它需要用另一个非singletoncd的bean B来执行一些操作。由于两个bean的生命周期是不同的,因此我们不能单的在bean A的配|中使用ref标签来要求Spring注入bean BQ因为那样会(x)让我们每ơ取得bean A旉使用同一个bean B的实例。回惛_面介l过的BeanFactoryAware接口Q我们可以让bean A实现该接口,q样可以在bean A内部使用beanFactory的genBeanҎ(gu)来获取bean B?jin)。只要我们将bean B配置为非singletoncdQ每ơ用getBeanҎ(gu)׃(x)得到一个新的bean B的实例?/div>
 (tng) (tng) (tng) (tng) (tng) (tng)使用查询Ҏ(gu)注入Q我可以不必实现M的Spring的接口,也不需要在bean A中显C的使用getBeanҎ(gu)来获得bean B。我们只需要在bean A中申明一个查询方法,然后在bean A的配|文件中指明该查询方法,那么Spring׃(x)自动的将bean B注入到bean A中去?jin)。由于查询方法注入的概念相对比较复杂Q因此我们还是通过具体的例子来直观的感受它是如何工作的?/div>
 (tng) (tng) (tng) (tng) (tng) (tng)在这个例子中Q我们创Z个非singleton的bean和两个实C(jin)同一个接口的singleton的beanQ一个通过传统的设值方法注入获得非singleton的beanQ另一个则通过查询Ҏ(gu)注入?/div>
//The MyHelper Bean
public class MyHelper {
 (tng) (tng) (tng) public void doSomethingHelpful() {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) // do something!
 (tng) (tng) (tng) }
}
//The DemoBean Interface
public interface DemoBean {
 (tng) (tng) (tng) public MyHelper getMyHelper();
 (tng) (tng) (tng) public void someOperation();
}
//The StandardLookupDemoBean
public class StandardLookupDemoBean implements DemoBean {
 (tng) (tng) (tng) private MyHelper helper;
 (tng) (tng) (tng) public void setMyHelper(MyHelper helper) {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) this.helper = helper;
 (tng) (tng) (tng) }
 (tng) (tng) (tng) public MyHelper getMyHelper() {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) return this.helper;
 (tng) (tng) (tng) }
 (tng) (tng) (tng) public void someOperation() {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) helper.doSomethingHelpful();
 (tng) (tng) (tng) }
}
//The AbstractLookupDemoBean
public abstract class AbstractLookupDemoBean implements DemoBean {
 (tng) (tng) (tng) public abstract MyHelper getMyHelper();
 (tng) (tng) (tng) public void someOperation() {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) getMyHelper().doSomethingHelpful();
 (tng) (tng) (tng) }
}
<beans>
 (tng) (tng) (tng) <bean id="helper" class="com.apress.prospring.ch5.mi.MyHelper" singleton="false"/>
 (tng) (tng) (tng) <bean id="abstractLookupBean" (tng)
class="com.apress.prospring.ch5.mi.AbstractLookupDemoBean">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <lookup-method name="getMyHelper" bean="helper"/>
 (tng) (tng) (tng) </bean>
 (tng) (tng) (tng) <bean id="standardLookupBean"
 (tng) (tng) (tng) class="com.apress.prospring.ch5.mi.StandardLookupDemoBean">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="myHelper">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <ref local="helper"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) </property>
 (tng) (tng) (tng) </bean>
</beans>
 (tng) (tng) (tng) (tng) (tng) 可以看到Q我们用了(jin)lookup-method来对查询Ҏ(gu)注入q行配置Q?strong>name属性告诉Spring需要覆写bean中的哪个Ҏ(gu)Q该Ҏ(gu)必须是没有参数的Qƈ且返回类型是我们需要获得的bean的类型,bean属性告诉Spring查询Ҏ(gu)需要返回哪个bean?/font>
 (tng) (tng) (tng) (tng) (tng) 通过DemoBean standardBean = (DemoBean)factory.getBean("standardLookupBean");获得standardBeanQ然后比较standardBean.getMyHelper() == standardBean.getMyHelper()Q可以发玎ͼ直接使用讄Ҏ(gu)注入Q每ơ获得的非singleton的bean实际上是同一个实例。而用查询方法注入,则会(x)每次得到一个新的实例,q实际上是因为我们用factory.getBean("abstractLookupBean")获得abstractBeanӞSpringҎ(gu)lookup-method的配|,覆写?jin)查询方法,从而返回一个新的bean实例Q正如前面提到的Q这是通过CGLIB包来实现的?/div>
 (tng) (tng) (tng) (tng) (tng) 值得注意的是Q我们将查询Ҏ(gu)定义为抽象的Q这不是必须的,但这么做能防止我们忘C(jin)配置lookup-methodQ从而用了(jin)I的Q当然不是我们期望的Q查询方法?/div>
 (tng) (tng) (tng) (tng) (tng) 好了(jin)Q让我们再来看看Ҏ(gu)替换Q虽然它被划分ؓ(f)Ҏ(gu)注入的一U,但它和我们以前接触到的注入方式有着很大的差异,以前我们都是注入一个beanQ而方法替换则是替换bean中的Ҏ(gu)实现。同查询Ҏ(gu)注入一P我们q是通过一个例子来理解Ҏ(gu)替换的用?/div>
//The ReplacementTarget Class
public class ReplacementTarget {
 (tng) (tng) (tng) public String formatMessage(String msg) {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) return "<h1>" + msg + "</h1>";
 (tng) (tng) (tng) }
 (tng) (tng) (tng) public String formatMessage(Object msg) {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) return "<h1>" + msg + "</h1>";
 (tng) (tng) (tng) }
}
 (tng) (tng) (tng) (tng) 现在׃某些原因Q我们需要修改以String为参数的Ҏ(gu)的实现方式,q且不能修改ReplacementTargetcȝ源代码,借助于Spring的方法替换,我们可以L地实现?/font>
 (tng) (tng) (tng) (tng) 首先Q创Z个实C(jin)MethodReplacer接口的类?/div>
public class FormatMessageReplacer implements MethodReplacer {
 (tng) (tng) (tng) public Object reimplement(Object target, Method method, Object[] args)
throws Throwable {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) ...
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) String msg = (String) args[0];
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) return "<h2>" + msg + "</h2>";
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) ...
 (tng) (tng) (tng) }
}
<beans>
 (tng) (tng) (tng) <bean id="methodReplacer"
 (tng) (tng) (tng) (tng)class="com.apress.prospring.ch5.mi.FormatMessageReplacer"/>
 (tng) (tng) (tng) (tng)<bean id="replacementTarget"
 (tng) (tng) (tng) class="com.apress.prospring.ch5.mi.ReplacementTarget">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <replaced-method name="formatMessage" replacer="methodReplacer">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <arg-type>String</arg-type>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) </replaced-method>
 (tng) (tng) (tng) </bean>
 (tng) (tng) (tng) <bean id="standardTarget"
 (tng) (tng) (tng) class="com.apress.prospring.ch5.mi.ReplacementTarget"/>
</beans>
 (tng) (tng) (tng) (tng) (tng) 通过replaced-method标签来配|需要替换的Ҏ(gu)Q?strong>name属性指明了(jin)需要替换的Ҏ(gu)名,replacer属性指明了(jin)用哪个bean来实现替换操作?strong>arg-type是用来指明需要替换的Ҏ(gu)的参数类型的Q在bean中有重蝲Ҏ(gu)Ӟ像ReplacementTargetcMP(j)Q指明参数类型可以让Spring明确知道需要替换的是哪个方法。值得注意的是Q?strong>arg-type是模式匹配的Q因此,String匹配String和StringBuffer?/font>
 (tng) (tng) (tng) (tng) (tng) Ҏ(gu)替换在很多场合都是有用的Q比如我们只想ؓ(f)一个特D的bean改变它所依赖的另一个bean的实现方法,而不影响其它bean的引用。最好是为每个需要替换的Ҏ(gu)Q或者是一l重载的Ҏ(gu)定义一个替换类Q而不要ؓ(f)众多毫不相关的方法用同一个替换类。这可以减少很多没必要的比较Q从而提高(sh)码的执行效率?/div>


刘璐 2006-12-21 10:23 发表评论
]]>《Pro Spring》学?fn)笔?4)Q-配置BeanFactory(1)http://www.tkk7.com/liulu/archive/2006/12/21/89211.html刘璐刘璐Thu, 21 Dec 2006 02:22:00 GMThttp://www.tkk7.com/liulu/archive/2006/12/21/89211.htmlhttp://www.tkk7.com/liulu/comments/89211.htmlhttp://www.tkk7.com/liulu/archive/2006/12/21/89211.html#Feedback0http://www.tkk7.com/liulu/comments/commentRss/89211.htmlhttp://www.tkk7.com/liulu/services/trackbacks/89211.html (tng)
 (tng) (tng) (tng) (tng) (tng) (tng)Spring使用spring-beans.dtd文g来定义BeanFactory的XML配置规范。可以在http://www.springframework.org/dtd/spring-beans.dtd扑ֈ该dtd文gQ当?dng)Spring的下载文件中也已l包含了(jin)该dtd文g。它被放在dist文g夹中?/div>
 (tng) (tng) (tng) (tng) (tng) 配置文g的根元素?strong>beansQ每个组件?strong>bean元素来定义,bean元素可以有许多属性,其中有两个是必须的:(x)id?strong>classQ这里说的id是必ȝq不意味着在配|文件中必须指定idQ后面会(x)详细说明Q。id表示lg的默认名Uͼclass表示lg的类型?/div>
 (tng) (tng) (tng) (tng) (tng) 如果使用讑ր注入,则需要?strong>property子标{,来指定组件的属性?/div>
<bean id="renderer" class="com.apress.prospring.ch2.StandardOutMessageRenderer">
 (tng) (tng) (tng) <property name="messageProvider">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <ref local="provider"/>
 (tng) (tng) (tng) </property>
</bean>
 (tng) (tng) (tng) (tng) (tng) 使用构造子注入Ӟ则?strong>constructor-arg子标{,来指定构造函数的参数?/font>
<bean id="provider" class="com.apress.prospring.ch4.ConfigurableMessageProvider">
 (tng) (tng) (tng) <constructor-arg>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>This is a configurable message</value>
 (tng) (tng) (tng) </constructor-arg>
</bean>
 (tng) (tng) (tng) (tng) (tng) 当构造函数有多个参数Ӟ可以使用constructor-arg标签?strong>index属性,index属性的g0开始?/font>
<bean id="provider" class="com.apress.prospring.ch4.ConfigurableMessageProvider">
 (tng) (tng) (tng) <constructor-arg index="0">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>first parameter</value>
 (tng) (tng) (tng) </constructor-arg>
 (tng) (tng) (tng) <constructor-arg index="1">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>second parameter</value>
 (tng) (tng) (tng) </constructor-arg>

</bean>
 (tng) (tng) (tng) (tng) 在用构造子注入Ӟ需要注意的问题是要避免构造子冲突的情况发生。考虑下面的情况:(x)
public class ConstructorConfusion {
 (tng) (tng) (tng) public ConstructorConfusion(String someValue) {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println("ConstructorConfusion(String) called");
 (tng) (tng) (tng) }
 (tng) (tng) (tng) public ConstructorConfusion(int someValue) {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println("ConstructorConfusion(int) called");
 (tng) (tng) (tng) }
}
 (tng) (tng) (tng) (tng) 使用如下配置文g
<bean id="constructorConfusion" class="com.apress.prospring.ch4.ConstructorConfusion">
 (tng) (tng) (tng) <constructor-arg>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>90</value>
 (tng) (tng) (tng) </constructor-arg>
</bean>
 (tng) (tng) (tng) (tng) 那么Q当实例化组?em>constructorConfusionӞ输?font color="#000000">ConstructorConfusion(String) calledQ也是说参数类型ؓ(f)String的构造函数被调用?jin),q显然不W合我们的要求。ؓ(f)?jin)让Spring调用参数为int的构造函数来实例化组?em>constructorConfusionQ我们需要在配置文g中明的告诉SpringQ需要用哪个构造函敎ͼq需要?strong>constructor-arg?strong>type属性?/font>
<bean id="constructorConfusion" class="com.apress.prospring.ch4.ConstructorConfusion">
 (tng) (tng) (tng) <constructor-arg type="int">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>90</value>
 (tng) (tng) (tng) </constructor-arg>
</bean>
 (tng) (tng) (tng) (tng) 我们不仅可以构造单个BeanFactoryQ而且可以建立有承关pȝ多个BeanFactory。只需要将父BeanFactory作ؓ(f)参数传给子BeanFactory的构造函数即可?/font>
BeanFactory parent =
 (tng) (tng) (tng) new XmlBeanFactory(new FileSystemResource("./ch4/src/conf/parent.xml"));
BeanFactory child =
 (tng) (tng) (tng) new XmlBeanFactory(new FileSystemResource("./ch4/src/conf/beans.xml"), parent);
 (tng) (tng) (tng) (tng) 如果子BeanFactory和父BeanFactory中含有名U相同的BeanQ那么在子BeanFactory中?/font>
<ref bean="sameNameBean"/>引用的将是子BeanFactory中的beanQؓ(f)?jin)引用父BeanFactory中的beanQ我们需要?strong>ref标签?strong>parent属?font color="#993366">Q?lt;ref parent="sameNameBean"/>?/font>
 (tng) (tng) (tng) (tng) Z(jin)注入集合属性,Spring提供?strong>list,map,set?strong>props标签Q分别对应List,Map,Set和Properties,我们甚至可以嵌套的用它们(List of Maps of Sets of ListsQ?/div>
<bean id="injectCollection" class="com.apress.prospring.ch4.CollectionInjection">
 (tng) (tng) (tng) <property name="map">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <map>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <entry key="someValue">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>Hello World!</value>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) </entry>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <entry key="someBean">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <ref local="oracle"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)</entry>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) </map>
 (tng) (tng) (tng) </property>
 (tng) (tng) (tng) <property name="props">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <props>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <prop key="firstName">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) Rob
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) </prop>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <prop key="secondName">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) Harrop
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) </prop>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) </props>
 (tng) (tng) (tng) </property>
 (tng) (tng) (tng) <property name="set">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <set>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>Hello World!</value>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <ref local="oracle"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) </set>
 (tng) (tng) (tng) </property>
 (tng) (tng) (tng) <property name="list">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <list>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>Hello World!</value>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <ref local="oracle"/>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)</list>
 (tng) (tng) (tng) </property>
</bean>


刘璐 2006-12-21 10:22 发表评论
]]>《Pro Spring》学?fn)笔?5)Q-配置BeanFactory(2)http://www.tkk7.com/liulu/archive/2006/12/21/89213.html刘璐刘璐Thu, 21 Dec 2006 02:22:00 GMThttp://www.tkk7.com/liulu/archive/2006/12/21/89213.htmlhttp://www.tkk7.com/liulu/comments/89213.htmlhttp://www.tkk7.com/liulu/archive/2006/12/21/89213.html#Feedback0http://www.tkk7.com/liulu/comments/commentRss/89213.htmlhttp://www.tkk7.com/liulu/services/trackbacks/89213.html (tng)
 (tng) (tng) (tng) (tng) (tng) (tng)BeanFactory中的每个bean都必至有一个唯一的名字,SpringZ(jin)灉|的支持各U情形,使用?jin)相对复杂的命名体系。如果我们ؓ(f)bean指定?strong>id属性,那么id属性的值将成ؓ(f)bean的名Uͼ如果没有指定id属性,Spring?strong>name属性的W一个|多个值用逗号或者分号分隔)(j)作ؓ(f)bean的名Uͼ如果name属性也没有指定QSpring用bean的类名(包括package的完整类名)(j)来作为bean的名Uͼ对于多个bean使用相同cd的情况,Spring?x)在cd后面d#2,#3{序h加以区别。不怎么_(d)使用id属性来指定bean的名UL一个不错的选择?/div>
 (tng) (tng) (tng) (tng) 在Spring中,所有bean默认都是以单例(singletonQŞ态存在的Q也是说我们通过BeanFactory的getBeanҎ(gu)获取的同一名称的bean是完全相同的Q即QbeanFactory.getBean("name")==beanFactory.getBean("name")。更改bean的Ş态ؓ(f)非singletonQ原型的Q?strong>prototypeQ是很容易的Q只需在bean标签中,指定singleton属性ؓ(f)false可以了(jin)?/div>
<bean id="nonSingleton" class="java.lang.String" singleton="false">
 (tng) (tng) (tng) ...
</bean>
 (tng) (tng) (tng) (tng) (tng) Z(jin)化配|,Springq提供了(jin)自动l装QAuto-WiringQbean的功能,有四U自动组装方式:(x)Ҏ(gu)名称QbyNameQ,Ҏ(gu)cdQbyTypeQ,构造子QConstructorQ以?qing)自动侦(autodetectQ?/font>
 (tng) (tng) (tng) (tng) (tng) 使用Ҏ(gu)名称自动l装ӞSpringҎ(gu)bean的属性的名称d扑֐名的bean配置?/font>
 (tng) (tng) (tng) (tng) (tng) 使用Ҏ(gu)cd自动l装ӞSpringҎ(gu)bean的属性的cdd扑֐cd的bean配置Q如果有多个同类型的bean配置Q那么Spring会(x)抛出异常Q以表示无法定使用哪个?/font>
 (tng) (tng) (tng) (tng) (tng) 使用构造子自动l装和用根据类型自动组装比较类|需要注意的是,使用构造子自动l装ӞSpring?x)匹配尽可能多的参数。例如,我们有一个bean拥有两个构造函敎ͼW一个接收一个Stringcd的参敎ͼW二个接收一个Stringcd和一个Integercd的参敎ͼq时Q如果在beanFactory的配|文件中有一个Stringcd的bean配置和一个Integercd的bean配置Q那么Spring会(x)使用W二个拥有两个参数的构造函数?/font>
 (tng) (tng) (tng) (tng) (tng) (tng) 使用自动侦测l装ӞSpring?x)在?gu)cd自动l装和根据构造子自动l装之间自动作出选择Q依据是Q如果bean拥有默认的(无参数的Q构造函敎ͼ那么Spring使用Ҏ(gu)cd自动l装的方式,否则Q用根据构造子自动l装的方式?/div>
 (tng) (tng) (tng) (tng) (tng) (tng) 有时候,我们可能?x)有多个bean拥有共同的类型,或是实现一些共同的接口Q因此它们会(x)有一些相同的配置Q如果能这些相同的配置提取出来Q各个bean只要l承q些相同的配|,然后d自己Ҏ(gu)的配|,会(x)大大减少重复的配|,降低发生错误的可能。Spring的beanl承机制是Zq样的目的而提供的。在Spring中,我们可以这些相同的配置提取出来Q配|成一个parent beanQ然后各个beanQchild beanQ可以承parent beanQ在child bean中,可以覆写parent bean中的配置Q也可以d自己的配|。parent bean是通过child bean的bean标签?strong>parent属性来指定的?/div>
<bean id="inheritParent" class="com.apress.prospring.ch4.inheritance.SimpleBean">
 (tng) (tng) (tng) <property name="name">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>Rob Harrop</value>
 (tng) (tng) (tng) </property>
 (tng) (tng) (tng) <property name="age">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>22</value>
 (tng) (tng) (tng) </property>
</bean>
<bean id="inheritChild" class="com.apress.prospring.ch4.inheritance.SimpleBean"
parent="inheritParent">
 (tng) (tng) (tng) <property name="age">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>35</value>
 (tng) (tng) (tng) </property>
</bean>
 (tng) (tng) (tng) (tng) (tng) 需要注意的是,bean的承体pdƈ不完全等同于java的类l承体系Q我们完全可以在C拥有相同cd的bean上用承,q不?x)带来Q何问题。因此,相对于java的承体pL_(d)Spring 的beanl承体系更类g模板cd?/font>


刘璐 2006-12-21 10:22 发表评论
]]>《Pro Spring》学?fn)笔?2)Q-何ؓ(f)Springhttp://www.tkk7.com/liulu/archive/2006/12/21/89209.html刘璐刘璐Thu, 21 Dec 2006 02:20:00 GMThttp://www.tkk7.com/liulu/archive/2006/12/21/89209.htmlhttp://www.tkk7.com/liulu/comments/89209.htmlhttp://www.tkk7.com/liulu/archive/2006/12/21/89209.html#Feedback0http://www.tkk7.com/liulu/comments/commentRss/89209.htmlhttp://www.tkk7.com/liulu/services/trackbacks/89209.html (tng)
 (tng) (tng) (tng) (tng) (tng) (tng)Spring通常被称为是构造Java工程的轻量框架。这其中包含?jin)两斚w的内容:(x)首先Q你可以使用Spring构造各UJava工程Q而不是像Apache的Struts那样Q仅仅局限于Web工程。其ơ,所谓轻量框架Qƈ不是指类的数量或是工E的规模是轻量的,用Spring的话_(d)轻量U就意味着更少的媄(jing)响,你可以很Ҏ(gu)的修改你的程序来获得Spring提供的各U好处,也可以很Ҏ(gu)的从你的工程中去除Spring。当?dng)需要注意的是,q仅仅是指Spring的核?j)组件。Springq提供了(jin)很多其它的组Ӟ像数据访问等Q用这些组Ӟ得你的工E与Spring框架形成耦合Q但是,相比于你获得的好处而言Q这些耦合Ҏ(gu)不得什么?/div>
 (tng) (tng) (tng) (tng) (tng) Spring框架的核?j)是Z控制反{(Invdersion Of Control, IOC)理论的,控制反{使得我们可以在外部来创徏和管理组件之间的依赖关系。例如:(x)cFoo依赖于一个Barcd的实例来执行某些操作Q传l的方式是,Foo使用new关键字或者从某个工厂cL创徏一个Barcȝ实例。然而,使用控制反{Q一个Barcd的实例将在运行时由外部程序提供。这U方式可以很形象的看作是在运行时Q将依赖的组件实例注入到当前lg中。因此,在某些时候,控制反{也被UCؓ(f)依赖注入(Dependency Injection, DI)。在Spring中,你可以认为控制反转就{同于依赖注入?/div>
 (tng) (tng) (tng) (tng) (tng) 依赖注入l我们带来的好处包括Q?/div>
 (tng) (tng) (tng) (tng) (tng) 1.减少?jin)组件关联的代码Q你不再需要在lg内部自己创徏需要用的其它lgQ它们会(x)在运行时自动被注入进来,特别是当某些lg需要通过JNDI来获得,或是Ҏ(gu)无法直接获得Q例如远E资源时QDI带来的好处就更加明显?jin)?/div>
 (tng) (tng) (tng) (tng) (tng) 2.依赖关pȝC码外Q这?x)带来两点好处,首先Q你可以在外部方便的理lg间的依赖关系Q而不需要重新编译代码。其ơ,你可以方便的切换某些依赖的实现类Q例如将PostgreSQL的DAO实现切换为Oracle的DAO实现?/div>
 (tng) (tng) (tng) (tng) (tng) 3.l一的依赖管理:(x)传统的散布在工程各处的管理依赖关pȝ代码不复存在,所有的依赖信息都集中在一个统一的地方,q得维护变得容易,同时降低?jin)发生错误的可能?/div>
 (tng) (tng) (tng) (tng) (tng) 4.提高?sh)(jin)可试性:(x)你可以很Ҏ(gu)的替换依赖类的实现方式,如用mock实现来代替真正的实现方式。假设我们需要测试业务对?Business Object, BO)Q我们就可以使用mock实现来代替真正的DAO实现Q从而避免真正地讉K数据库,q大大提高(sh)(jin)试的效率?/div>
 (tng) (tng) (tng) (tng) (tng) 5.遵@良好的设计方式:(x)使用DI通常意味着遵@面向接口的设计方式。毫无疑问,面向接口是一U良好的设计方式?/div>
 (tng) (tng) (tng) (tng) (tng) Spring框架q包括了(jin)以下q些斚w的内容:(x)
 (tng) (tng) (tng) (tng) (tng) 1.面向斚w的编E?Aspect Oriented Programming, AOP)
 (tng) (tng) (tng) (tng) (tng) 2.数据讉K(Accessing Data in Spring)
 (tng) (tng) (tng) (tng) (tng) 3.事务理(Managing Transactions)
 (tng) (tng) (tng) (tng) (tng) 4.化J2EE的整?Simplifying and Integrating with J2EE)
 (tng) (tng) (tng) (tng) (tng) 5.Web层的MVC框架(MVC in the (tng)Web Tier)
 (tng) (tng) (tng) (tng) (tng) 6.对远E访问的支持(Remoting Support)
 (tng) (tng) (tng) (tng) (tng) 7.邮g支持(Mail Support)
 (tng) (tng) (tng) (tng) (tng) 8.d安排的支?Job Scheduling Support)
 (tng) (tng) (tng) (tng) (tng) 9.化的异常处理(Simplified Exception Handling)
 (tng) (tng) (tng) (tng) (tng) 10.源代码的元数据(Source Level Metadata)


刘璐 2006-12-21 10:20 发表评论
]]>《Pro Spring》学?fn)笔?3)Q-Spring中的IOChttp://www.tkk7.com/liulu/archive/2006/12/21/89210.html刘璐刘璐Thu, 21 Dec 2006 02:20:00 GMThttp://www.tkk7.com/liulu/archive/2006/12/21/89210.htmlhttp://www.tkk7.com/liulu/comments/89210.htmlhttp://www.tkk7.com/liulu/archive/2006/12/21/89210.html#Feedback0http://www.tkk7.com/liulu/comments/commentRss/89210.htmlhttp://www.tkk7.com/liulu/services/trackbacks/89210.html (tng)
 (tng) (tng) (tng) (tng) (tng) (tng)控制反{包括两种cdQ依赖查找(Dependency LookupQ和依赖注入QDependency InjectionQ,我们主要讨论的是依赖注入?/div>
 (tng) (tng) (tng) (tng) (tng) 依赖注入可以分ؓ(f)两种cdQ构造子注入QConstructor Dependency InjectionQ和讑ր注入(Setter Dependency InjectionQ?/div>
 (tng) (tng) (tng) (tng) (tng) 构造子注入Q组件的依赖关系是通过构造函数来提供的,每个依赖关系对应构造函数的各个参数QIOC容器在实例化lgӞ通过构造函数注入依赖关pR?/div>
public class ConstructorInjection {
 (tng) (tng) (tng) private Dependency dep;
 (tng) (tng) (tng) public ConstructorInjection(Dependency dep) {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) this.dep = dep;
 (tng) (tng) (tng) }
}
构造子注入适用于在使用某个lg之前Q确保所有的依赖关系都已注入?/div>
 (tng) (tng) (tng) (tng) (tng) 讑ր注入,lg的依赖关pL通过JavaBean形式的setterҎ(gu)注入的,IOC容器通过调用相应的setҎ(gu)注入依赖关系?br />public class SetterInjection {
 (tng) (tng) (tng) private Dependency dep;
 (tng) (tng) (tng) public void setMyDependency(Dependency dep) {
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) this.dep = dep;
 (tng) (tng) (tng) }
}
讑ր注入适用于需要给某些依赖关系提供默认值的情况?/div>
 (tng) (tng) (tng) (tng) (tng) Spring IOC容器的核?j)是BeanFactoryQBeanFactory负责理lg以及(qing)lg间的依赖关系。术?strong>bean在Spring中代表由容器理的Q何组件。Spring提供?jin)两U常用的BeanFactory实现QDefaultListableBeanFactory和XmlBeanFactory?/div>
 (tng) (tng) (tng) (tng) (tng) 在BeanFactory中,每个bean都至有一个名Uͼ作ؓ(f)唯一标识Q如果bean拥有多个名称的话Q那么除W一个名U外的其它名U都被认ؓ(f)是别名?/div>
 (tng) (tng) (tng) (tng) (tng) DefaultListableBeanFactory可以使用PropertiesBeanDefinitionReader或者XmlBeanDefinitionReaderQ当然还可以是其它Q何实C(jin)BeanDefinitionReader接口的Bean定义d器)(j)来读取配|文件?/div>
//使用PropertiesBeanDefinitionReader
private static BeanFactory getBeanFactory() throws Exception {
 (tng) (tng) (tng) // get the bean factory
 (tng) (tng) (tng) DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
 (tng) (tng) (tng) // create a definition reader
 (tng) (tng) (tng) PropertiesBeanDefinitionReader rdr = new PropertiesBeanDefinitionReader(factory);
 (tng) (tng) (tng) // load the configuration options
 (tng) (tng) (tng)
Properties props = new Properties();
 (tng) (tng) (tng) props.load(new FileInputStream("./ch2/src/conf/beans.properties"));
 (tng) (tng) (tng) rdr.registerBeanDefinitions(props);
 (tng) (tng) (tng) return factory;
}
//使用XmlBeanDefinitionReader
private static BeanFactory getBeanFactory() throws Exception {
 (tng) (tng) (tng) // get the bean factory
 (tng) (tng) (tng) DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
 (tng) (tng) (tng) // create a definition reader
 (tng) (tng) (tng) XmlBeanDefinitionReader rdr = new XmlBeanDefinitionReader(factory);
 (tng) (tng) (tng) // load the configuration options
 (tng) (tng) (tng) rdr.loadBeanDefinitions(new FileSystemResource("ch4/src/conf/beans.xml"));
 (tng) (tng) (tng) (tng)return factory;
}
 (tng) (tng) (tng) (tng) (tng) XmlBeanFactoryl承?jin)DefaultListableBeanFactoryQ在使用XML配置文g时可以简化代码的~写Q这也是我们最常用的BeanFactory?/div>
private static BeanFactory getBeanFactory() throws Exception {
 (tng) (tng) (tng) XmlBeanFactory factory =
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) new XmlBeanFactory(new FileSystemResource("ch4/src/conf/beans.xml"));
 (tng) (tng) (tng) (tng)return factory;
}
 (tng) (tng) (tng) (tng) (tng) 获得?jin)BeanFactory对象后,我们可以用bean的名U来获取我们需要的lg对象?jin)?/div>
Oracle oracle = (Oracle)factoyr.get("oracle");


刘璐 2006-12-21 10:20 发表评论
]]>(?《Pro Spring》学?fn)笔?1)Q-写在前面的话http://www.tkk7.com/liulu/archive/2006/12/21/89208.html刘璐刘璐Thu, 21 Dec 2006 02:19:00 GMThttp://www.tkk7.com/liulu/archive/2006/12/21/89208.htmlhttp://www.tkk7.com/liulu/comments/89208.htmlhttp://www.tkk7.com/liulu/archive/2006/12/21/89208.html#Feedback0http://www.tkk7.com/liulu/comments/commentRss/89208.htmlhttp://www.tkk7.com/liulu/services/trackbacks/89208.html (tng) (tng) (tng) (tng) (tng) 在网上也看到q很多牛人对Spring的评论文章,其中不乏一些颇有微词的评论。当?dng)M事务都不可能十全十美的,我只是一个普通的JavaE序员,q无法站在一定的高度Q看到Springq样那样的不뀂我感觉到的只是Springl我带来的好处和便利Q因此我选择?jin)Spring?/div>
 (tng) (tng) (tng) (tng) (tng) 接下来的文字Q记录的只是在学?fn)《Pro Spring》这本书的过E中Q我觉得需要着重了(jin)解的部分Q大部分文字属于抄书Q外加一点点个h的理解?/div>
 (tng) (tng) (tng) (tng) (tng) 感谢Rob Harrop和Jan Machacekl我们带来了(jin)q本通俗易懂的Spring入门书籍?/div>

刘璐 2006-12-21 10:19 发表评论
]]>springIDEhttp://www.tkk7.com/liulu/archive/2006/11/18/81936.html刘璐刘璐Sat, 18 Nov 2006 08:13:00 GMThttp://www.tkk7.com/liulu/archive/2006/11/18/81936.htmlhttp://www.tkk7.com/liulu/comments/81936.htmlhttp://www.tkk7.com/liulu/archive/2006/11/18/81936.html#Feedback0http://www.tkk7.com/liulu/comments/commentRss/81936.htmlhttp://www.tkk7.com/liulu/services/trackbacks/81936.html首先试link方式安装Q无法用。上|查询后Q网友都认ؓ(f)应该用updata方式安装

1.打开eclipseQ菜?help"->"software updates"->"find and install"
2.在弹出的界面中选择“Search for new features to install?br />3.q一步可分成两种情况Q?br />a.如果本地已经下蝲SpringIDE的压~包Q请解压C个目录(比如SpringIDEQ,里面有两个目录(features、pluginsQ和一个文件site.xmlQ在弹出的界面中选择"New Local Site"Q指到前面的解压后目录(SpringIDEQ,点“OK”,?Name"中输入“SpringIDE Update?br />b.如果没有下蝲SpringIDE的压~包Q在弹出的界面中选择“New Remote Site”,?Name"中输入“SpringIDE Update”,在“URL”中输入“http://springide.org/updatesite/”,点“OK?br />4.选中"SpringIDE Update"Q点“finish?开始搜索站点的更新信息
5.在搜索界面的界面中选中要更新的Ql?br />因ؓ(f)我的|络有防火墙隔离Q所以直接下载了(jin)springide_updatesite_1.2.1.zip在本地安装?/p>

安装q程中,出现error retrieving “feature.xml“的错误Q这时候删除了(jin)根目录的site.xml文gQ就可以updata?/p>

另外QspringIDE的用方法可以参?http://www.volitation.net/Dynamic/print.asp?SelectID=101



刘璐 2006-11-18 16:13 发表评论
]]>
spring ~程入门十大问题解答http://www.tkk7.com/liulu/archive/2006/09/14/69521.html刘璐刘璐Thu, 14 Sep 2006 00:25:00 GMThttp://www.tkk7.com/liulu/archive/2006/09/14/69521.htmlhttp://www.tkk7.com/liulu/comments/69521.htmlhttp://www.tkk7.com/liulu/archive/2006/09/14/69521.html#Feedback0http://www.tkk7.com/liulu/comments/commentRss/69521.htmlhttp://www.tkk7.com/liulu/services/trackbacks/69521.html你可以通过下列途径学习(fn)springQ?br />(1) spring下蝲包中doc目录下的MVC-step-by-step和sample目录下的例子都是比较好的spring开发的例子?

(2) AppFuse集成?jin)目前最行的几个开源轻量框架或者工具Ant,XDoclet,Spring,Hibernate(iBATIS),JUnit,Cactus,StrutsTestCase,Canoo's WebTest,Struts Menu,Display Tag Library,OSCache,JSTL,Struts ?br />你可以通过AppFuse源代码来学习(fn)spring?br />AppFuse|站Q?a >http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuse

(3)Spring 开发指?夏昕)Q?a >http://www.xiaxin.net/Spring_Dev_Guide.rarQ?br />一本spring的入门书c?里面介绍?jin)反转控制和依赖注射的概念,以?qing)spring的bean理Qspring的MVCQspring和hibernteQiBatis的结合?/p>

(4) spring学习(fn)的中文论?br />SpringFramework中文论坛(http://spring.jactiongroup.net)
Java视线论坛(http://forum.javaeye.com)的spring栏目

2、利用Spring框架~程Qconsole打印出log4j:WARN Please initialize the log4j system properlyQ?br />说明你的log4j.properties没有配置。请把log4j.properties攑ֈ工程的classpath中,eclipse的classpath为bin目录Q由于编译后src目录下的文g?x)拷贝到bin目录下,所以你可以把log4j.properties攑ֈsrc目录下?br />q里l出一个log4j.properties的例子:(x)

log4j.rootLogger=DEBUG,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %5p (%F:%L) - %m%n


3、出?java.lang.NoClassDefFoundError?
一般情况下是由于你没有把必要的jar包放到l(f)ib中?/p>

比如你要采用spring和hibernateQ带事务支持的话Q,你除?jin)spring.jar外还需要hibernat.jar、aopalliance.jar、cglig.jar、jakarta-commons下的几个jar包?/p>

http://www.springframework.org/download.html下蝲spring开发包Q提供两Uzip?br />spring-framework-1.1.3-with-dependencies.zip和spring-framework-1.1.3.zipQ我你下载spring-framework-1.1.3-with-dependencies.zip。这个zip解压~后比后者多一个lib目录Q其中有hibernate、j2ee、dom4j、aopalliance、jakarta-commons{常用包?br />

4、java.io.FileNotFoundException: Could not open class path resource [....hbm.xml],提示找不到xml文gQ?br />原因一般有两个Q?br />(1)该xml文g没有在classpath中?br />(2)applicationContext-hibernate.xml中的xml名字没有带包名。比如:(x)
<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="dataSource"><ref bean="dataSource"/></property>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="mappingResources">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <list>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>User.hbm.xml</value> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) 错,改ؓ(f)Q?<value>com/yz/spring/domain/User.hbm.xml</value>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) </list>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) </property>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="hibernateProperties">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <props>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <prop key="hibernate.dialect"> net.sf.hibernate.dialect.MySQLDialect </prop>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <prop key="hibernate.show_sql">true</prop>
 (tng) (tng) (tng) (tng) (tng)  (tng) (tng)</props>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) </property>
</bean>


5、org.springframework.beans.NotWritablePropertyException: Invalid property 'postDao' of bean classQ?br />出现异常的原因是在application-xxx.xml中property name的错误?br /><property name="...."> 中name的名字是与bean的setҎ(gu)相关的,而且要注意大写?br />比如
public class PostManageImpl extends BaseManage implements PostManage {
 (tng) (tng) (tng) private PostDAO dao = null;
 (tng) (tng) (tng) public void setPostDAO(PostDAO postDAO){
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) this.dao = postDAO;
 (tng) (tng) (tng) }
}
那么xml的定义应该是Q?br /><bean id="postManage" parent="txProxyTemplate">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="target">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <bean class="com.yz.spring.service.implement.PostManageImpl">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="postDAO"><ref bean="postDAO"/></property> (tng) (tng) (tng) ?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="dao"><ref bean="postDAO"/></property> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)  (tng)?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) </bean>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) </property>
</bean>

6、Spring中如何实C务管理?
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)首先Q如果用mysqlQ确定mysql为InnoDBcd?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)事务理的控制应该放到商业逻辑层。你可以写个处理商业逻辑的JavaBeanQ在该JavaBean中调用DAOQ然后把该Bean的方法纳入spring的事务管理?br />
比如Qxml文g定义如下Q?br /><bean id="txProxyTemplate" abstract="true"
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="transactionManager"><ref bean="transactionManager"/></property>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="transactionAttributes">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <props>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <prop key="save*">PROPAGATION_REQUIRED</prop>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <prop key="remove*">PROPAGATION_REQUIRED</prop>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <prop key="*">PROPAGATION_REQUIRED</prop>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) </props>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) </property>
</bean>

<bean id="userManage" parent="txProxyTemplate">
 (tng) (tng) (tng) (tng) (tng) <property name="target">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <bean class="com.yz.spring.service.implement.UserManageImpl">
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="userDAO"><ref bean="userDAO"/></property>
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) </bean>
 (tng) (tng) (tng) (tng) (tng) </property>
</bean>

com.yz.spring.service.implement.UserManageImpl是我们的实现商业逻辑的JavaBean。我们通过parent元素声明其事务支持?br />

7、如何管理Spring框架下更多的JavaBeanQ?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)JavaBean多Qspring配置文gp大,q样不易l护。ؓ(f)?jin)配置清晰Q我们可以将JavaBean分类理Q放在不同的配置文g中?应用启动时将所有的xml同时加蝲?br />比如Q?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)DAO层的JavaBean攑ֈapplicationContext-hibernate.xml中,商业逻辑层的JavaBean攑ֈapplicationContext-service.xml中。然后启动类中调用以下代码蝲入所有的ApplicationContext?br />
String[] paths = {"com/yz/spring/dao/hibernate/applicationContext-hibernate.xml",
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)  (tng) "com/yz/spring/service/applicationContext-service.xml"};
ctx = new ClassPathXmlApplicationContext(paths);


8、web应用中如何加载ApplicationContextQ?br />可以通过定义web.xmlQ由web容器自动加蝲?/p>

 (tng)<servlet>
 (tng) (tng)<servlet-name>context</servlet-name>
 (tng) (tng)<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
 (tng) (tng)<load-on-startup>1</load-on-startup>
 (tng)</servlet>
 (tng)
 (tng)<context-param>
 (tng) (tng)<param-name>contextConfigLocation</param-name>
 (tng) (tng)<param-value>/WEB-INF/applicationContext-hibernate.xml</param-value>
 (tng) (tng)<param-value>/WEB-INF/applicationContext-service.xml</param-value>
 (tng)</context-param>

9、在spring中如何配|的log4j?
在web.xml中加入以下代码即可?br /><context-param>
 (tng) (tng)<param-name>log4jConfigLocation</param-name>
 (tng) (tng)<param-value>/WEB-INF/log4j.properties</param-value>
</context-param>

10、Spring框架入门的编E问题解决了(jin)Q我该如何更深地领会(x)Spring框架呢?
q两本书你该ȝ看。这两本书是由Spring的作者Rod Johnson~写的?br />Expert One on one J2EE Design and Development
Expert One on one J2EE Development Without EJB
你也该看看martinfowler的Inversion of Control Containers and the Dependency Injection pattern?br />http://www.martinfowler.com/articles/injection.html

再好好研M下spring的文档?br />http://www.jactiongroup.net/reference/html/index.htmlQ中文版Q未全部译Q?br />
q有是多实践吧?/p>

刘璐 2006-09-14 08:25 发表评论
]]>
վ֩ģ壺 ޳?vƬ| պƷƵ| ͵޾Ʒ| ¹޾ƷӰԺ| ձþþþĻ| ƵպƵ| ޾Ʒѹۿ| ɫ͵͵͵վɫ͵һ| ޳avƬ| Ƶ| 2016| ŷһ| Ʒ| һһëƬѲ| þԭƷ| avѸ߳ˮ| պѵӰַ| ߹ۿhƬ| Ů18һëƬѹۿ| ûվɫƵ| ĻӰѹۿַ| ŷպþAV| ɫWWWַ| ַ߹ۿ㶮| ޹˾þۺһ| ŷ޹SUV| wwwѹۿվ| þóѴƬ| վ߹ۿ| һ| һ| ŷպۺ߶| ˳7777| ѿƸappһ»ɫ¼| Ƶվ߿| þw5www| Ƶ| ޾Ʒɫ| ëƬƵ| ŮܳƵ| Ѳ߹ۿAV|