这个是基于example1的项目。
首先:创建HelloStr
package com.openv.spring;
/**
* HelloStr接口
* @author jiangao
*
*/
public interface HelloStr {
public String getContent();
}
其次,声明FileHelloStr类实现了HelloStr接口,
public class FileHelloStr implements HelloStr{
……
}
然后重构HelloWorld类
private HelloStr hStr;
public HelloWorld(HelloStr hStr) {
this.hStr = hStr;
}
public String getContent() {
// FileHelloStr fhStr = new FileHelloStr("Helloworld.properties");
// String helloworld = fhStr.getContent();
// return helloworld;
return hStr.getContent();
}
最后,重构客户端应用:
public static void main(String[] args) {
// HelloWorld hw = new HelloWorld();
// log.info(hw.getContent());
FileHelloStr fhStr = new FileHelloStr("HelloWorld.properties");
HelloWorld hw = new HelloWorld(fhStr);
log.info(hw.getContent());
}
运行结果:
2011-9-28 22:20:21 com.openv.client.HelloWorldClient main
信息: "HelloWorld"
跟第一天的运行结果一样。你肯定注意到,HelloWorld不再操作FileHelloStr了,而是对FileHelloStr实现的HelloStr接口进行操作。从而,现在的HelloWorld更加通用了,但是,现有的应用还是存在一个问题,即开发者必须在其实现的客户代码中创建FileHelloStr对象,并连接到HelloWorld中。因此,开发者需要借助于工厂类,以注入HelloWorld和FileHelloStr的依赖性。
在example2的基础上继续创建, 创建一个工厂 HelloWorldFactory
package com.openv.spring;
import com.openv.bean.HelloWorld;
/**
* 注入HelloWorld和HelloStr依赖性
*
* @author jiangao
*/
public class HelloWorldFactory {
public static HelloWorld getFileHelloWorld() {
HelloStr hStr = new FileHelloStr("HelloWorld.properties");
HelloWorld hw = new HelloWorld(hStr);
return hw;
}
}
然后重构一个用户代码:
package com.openv.client;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.openv.bean.HelloWorld;
import com.openv.spring.FileHelloStr;
import com.openv.spring.HelloWorldFactory;
/**
* 客户端应用
*
* @author jiangao
*
*/
public class HelloWorldClient {
protected static final Log log = LogFactory.getLog(HelloWorldClient.class);
public static void main(String[] args) {
// HelloWorld hw = new HelloWorld();
// log.info(hw.getContent());
// FileHelloStr fhStr = new FileHelloStr("HelloWorld.properties");
// HelloWorld hw = new HelloWorld(fhStr);
HelloWorld hw=HelloWorldFactory.getFileHelloWorld();
log.info(hw.getContent());
}
}
运行结果:
2011-9-28 23:13:19 com.openv.client.HelloWorldClient main
信息: "HelloWorld"
其中,HelloWorldFactory负责创建和集成客户应用所需的对象。至此,你就可以借助于依赖注入(HelloWorldFactory类)实现了控制反转。
注意:
以上的例子都没有用到Spring,借助于Spring提供的核心工厂模式,开发者能够消除手工编写工厂类的需要。即将创建对象的工作交由Spring负责,从而消除了对工厂类、方法的需要。
例四:
应用系统越大,相应的工厂类越多。一般情况下,工厂类都是简单的,仅提供静态方法和变量的单实例。它们将创建对象,并将这些对象绑定在一起。显而易见,这将存在大量的重复代码。
Spring框架最基本的一项功能是,充当创建对象的工厂。其具体工作步骤如下:
1.读取并分析Spring配置文件(比如基于xml文件格式)
2.通过java反射机制,创建并集成上述配置文件中定义的对象。
3.将创建的对象传回给开发者的应用代码。因此,开发者不用编写工厂类,其前提是使用Spring框架。
首先,编写Spring配置文件,即beans.xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="helloworld" class="com.openv.bean">
<constructor-arg ref="fileHelloStr" />
</bean>
<bean id="fileHelloStr" class="com.openv.FileHelloStr">
<constructor-arg ref="HelloWorld.properties" />
</bean>
</beans>
由于Spring配置文件的根元素是beans,它含有一个或多个bean元素。其中,bean元素用于描述应用代码中的javabean对象。
通过name属性能够唯一标志某javabean。比如,能够通过“helloworld”字符串能够访道HelloWorld对象。另外,class属性能够确定待定实例化类,比如上述代码中的class="com.openv.bean"。当Spring创建javabean对象的实例的时候,bean的COntructor-org子元素将值传入到其构造器中,比如上述中的helloWorld.properties.如果构造器存在多个参数,就使用index属性(或者type属性)指定对应的参数的取值。
而ref元素能够引用Spring配置文件中的其他已定义的JavaBean.比如 ,上述 helloworld引用 了 fileHello。为将 取值传递给 构造器()或者设置方法 ,需要使用value元素。其中,spring能够将value元素取值转换为相应的java类型。
public static void main(String[] args) {
// 第一次代码
// HelloWorld hw = new HelloWorld();
// log.info(hw.getContent());
// 第二次修改代码
// FileHelloStr fhStr = new FileHelloStr("HelloWorld.properties");
// HelloWorld hw = new HelloWorld(fhStr);
//
// HelloWorld hw=HelloWorldFactory.getFileHelloWorld();
// log.info(hw.getContent());
// 第三次修改代码
Resource resource = new ClassPathResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);
HelloWorld hs = (HelloWorld) factory.getBean("helloworld");
log.info(hs.getContent());
}
运行结果:
2011-9-29 0:11:08 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans.xml]
2011-9-29 0:11:08 com.openv.client.HelloWorldClient main
信息: "HelloWorld"
创建了两个单实例的helloworld和fileHelloStr,即spring默认时仅创建单实例的javabean,通过spring配置文件中bean元素的singleton属性能够控制创建java实例的方式。