Spring的核心机制是依赖注入(Dependency Inversion),也成为控制反转。学习它之前先引入一个设计模式-工厂模式。
5.2.1 工厂模式
工厂模式是指当甲组件需要乙组件协助时,不直接创建乙组件的实例对象,而是通过乙组件的工厂创建,这样甲组件无需通过硬编码的方式与乙组件耦合,只需与乙组件的工厂耦合。
创建一个Java Project,命名为“FactoryExample”。在src文件夹下建立包face,在该包下建立接口Human,代码如下:
package face;public interface Human { void eat(); void walk();}
在src文件夹下建立包iface,在该包下建立Chinese类和American类,分别实现Human接口。
Chinese.java代码如下:
package iface;import face.Human;public class Chinese implements Human{ public void eat() { System.out.println("中国人很会吃!"); } public void walk() { System.out.println("中国人健步如飞!"); }}
American.java代码如下:
package iface;import face.Human;public class American implements Human{public void eat() {System.out.println("美国人吃西餐!"); } public void walk() { System.out.println("美国人经常坐车!"); }}
在src文件夹下建包factory,在该包内建立工厂类Factory,代码如下:
package factory;import iface.American;import iface.Chinese;import face.Human;public class Factory {public Human getHuman(String name){if(name.equals("Chinese")){return new Chinese();}else if(name.equals("American")){return new American();}else{throw new IllegalArgumentException("参数不正确");} }}
在src文件夹下建包test,在该包内建立测试类Test,代码如下:
package test;import face.Human;import factory.Factory;public class Test { public static void main(String[] args) { Human human=null; human=new Factory().getHuman("Chinese"); human.eat(); human.walk();human=new Factory().getHuman("American"); human.eat(); human.walk(); }}
该程序为Java应用程序,直接运行可看出结果,如图5.2所示。
图5.2 工厂模式运行结果
5.2.2 依赖注入应用
上面讲到了工厂模式,Sping提供了更好的办法实现,就是依赖注入。
1. 为项目添加Spring开发能力
右击项目名,选择【MyEclipse】→【Add Spring Capabilities…】菜单项,将出现如图5.3所示的对话框,选中要应用的Spring的版本及所需的类库文件。
图5.3 选择Spring版本及类库对话框
选择结束后,单击【Next】按钮,出现如图5.4所示的界面。用于创建Spring的配置文件。
单击【Finish】按钮完成。项目的src文件夹下会出现名为applicationContext.xml的文件,这就是Spring的核心配置文件。
图5.4 创建Spring的配置文件
2. 修改测试类
配置完成后,就可以修改Test类。对象ctx就相当于原来的Factory工厂,原来的Factory可以删除掉了。
package test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.FileSystemXmlApplicationContext;import face.Human;import factory.Factory;public class Test { public static void main(String[] args) { ApplicationContext ctx=new FileSystemXmlApplicationContext("src/applicationContext.xml"); Human human = null; human = (Human) ctx.getBean("chinese"); human.eat(); human.walk(); human = (Human) ctx.getBean("american"); human.eat(); human.walk(); }}
在applicationContext.xml配置如下:
id是ctx.getBean的参数值,一个字符串。class是一个类(包名+类名)。
human = (Human) ctx.getBean("american");human = (Human) ctx.getBean("american");
3. 运行
运行该测试类,结果如图5.5所示。
图5.5 运行结果
5.2.3 注入的两种方式
所谓依赖注入,就是调用另一个对象时,无需在代码中创建被调用者,而是依赖于外部的注入。
1. 设置注入
设置注入是通过setter方法注入被调用者的实例。这种方法简单、直观,很容易理解,因而Spring的依赖注入被大量使用,下面举例说明。
创建一个Java Project,命名为“FactoryExample1”。在项目的src文件夹下建立下面的源文件。
Human的接口,Human.java,代码如下:
public interface Human {void speak();}
Language接口,Language.java,代码如下:
public interface Language {public String kind();}
下面是Human实现类Chinese.java代码:
public class Chinese implements Human{ private Language lan; public void speak() {System.out.println(lan.kind()); } public void setLan(Language lan) { this.lan = lan; }}
下面是Language实现类English.java代码:
public class English implements Language{ public String kind() {return "中国人也会说英语!"; }}
下面通过Spring的配置文件来完成其对象的注入。代码如下:
测试代码如下:
import org.springframework.context.ApplicationContext;import org.springframework.context.support.FileSystemXmlApplicationContext;public class Test { public static void main(String[] args) { ApplicationContext ctx = new FileSystemXmlApplicationContext("src/applicationContext.xml"); Human human = null; human = (Human) ctx.getBean("chinese"); human.speak(); }}
程序执行结果如图5.6所示。
图5.6 程序运行结果
2. 构造注入
这种方式在构造实例时,已经完成了属性的初始化。
例如,只要对前面的Chinese类进行简单的修改:
public class Chinese implements Human{ private Language lan; public Chinese(){}; // 构造注入所需要的带参数的构造函数 public Chinese(Language lan){ this.lan=lan; } public void speak() { System.out.println(lan.kind()); }}
配置文件也需要做简单的修改:
附:目录