想一下之前学的Java,如果某个类需要引用某个对象,则需要手动new一个出来。这样带来的一个问题就是,若被引用的类发生改动或被删除,则引用它的所有类都会报错。因为两个类耦合在一起了。解决的办法就是不由类本身主动进行引用,而由一个第三方的配置文件控制。这就是所谓的控制反转。下面用一个例子说明。
在演示之前需要准备环境。
IDE:Eclipse Java EE Mars
Spring所需jar包:官网不提供下载,而推荐使用Maven或Gradle构建项目。不过为了方便演示仍使用原始形式,下面的地址可以用来下载。
http://repo.springsource.org/libs-release-local/org/springframework/
准备就绪之后,新建一个Java项目,然后将需要的jar包导入。实现这个例子需要以下7个jar包,后四个可以在下载的Spring包中找到,前三个需要单独下载。
导入jar包完成之后,Add Library,选择JUnit。然后构建如下目录。
HelloApi.java:
package com.erving; public interface HelloApi { public void sayHello(); }
HelloImpl.java:
package com.erving; public class HelloImpl implements HelloApi { @Override public void sayHello() { System.out.println("Hello World!"); } }
业务逻辑的接口和实现写好之后,接下来就要定义配置文件,使其能够被IOC容器管理,配置文件如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <bean id="hello" class="com.erving.HelloImpl"></bean> </beans>
最后,如何调用这个功能呢?只需三步:一是实例化IOC容器;二是从容器中获取Bean;三是调用接口完成功能。
HelloTest.java:
package com.erving; import static org.junit.Assert.*; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class HelloTest { @Test public void testHelloWorld() { ApplicationContext context = new ClassPathXmlApplicationContext("helloworld.xml"); HelloApi helloApi = context.getBean("hello", HelloApi.class); helloApi.sayHello(); } }
尤其要注意的是:配置文件中指定Bean的类,是功能的实现(Implement);从IOC容器获取Bean,使用的是功能的接口(Interface)。