基本上 Spring 是 dependency-injection 的框架,这是一种允许构建非常解耦的系统的模式。
问题
例如,假设您需要列出系统的用户并因此声明一个名为UserLister的接口:
public interface UserLister {
List<User> getUsers();
}
也许还有一个访问数据库以获取所有用户的实现:
public class UserListerDB implements UserLister {
public List<User> getUsers() {
// DB access code here
}
}
在您看来,您需要访问一个实例(只是一个示例,请记住):
public class SomeView {
private UserLister userLister;
public void render() {
List<User> users = userLister.getUsers();
view.render(users);
}
}
请注意,上面的代码没有初始化变量userLister。我们应该做什么?如果我像这样显式实例化对象:
UserLister userLister = new UserListerDB();
...我将视图与访问数据库的类的实现结合起来。如果我想从数据库实现切换到另一个从逗号分隔文件中获取用户列表的实现(记住,这是一个示例),该怎么办?在这种情况下,我会再次转到我的代码并将上面的行更改为:
UserLister userLister = new UserListerCommaSeparatedFile();
这样的小程序没有问题,但是......在一个有数百个视图和类似数量的业务类的程序中会发生什么?维护成为一场噩梦!
Spring(依赖注入)方法
Spring 所做的是通过使用 XML 文件或注释将类连接,这样所有对象都由 Spring 实例化和初始化,并在右侧 injected位置(Servlet、Web 框架、业务类、DAO 等,等等……)。
回到 Spring 中的示例,我们只需要为 userLister 字段设置一个设置器,并拥有一个像这样的 XML 文件:
<bean id="userLister" class="UserListerDB" />
<bean class="SomeView">
<property name="userLister" ref="userLister" />
</bean>
或者更简单地用@Inject注释我们视图类中的文件:
@Inject
private UserLister userLister;
这样,当视图被创建时神奇地就会有一个UserLister准备好工作。
List<User> users = userLister.getUsers(); // This will actually work
// without adding any line of code
太棒了!不是吗?
-
如果你想使用
UserLister 接口的另一个实现怎么办?只需更改 XML。
-
如果没有准备好
UserLister 实现怎么办? 编写 UserLister 的临时模拟实现并简化视图的开发。
-
如果我不想再使用 Spring 怎么办? 不要使用它!您的应用程序没有耦合到它。 Inversion of Control 声明:“应用程序控制框架,而不是框架控制应用程序”。
还有一些其他的依赖注入选项,在我看来,除了简单、优雅和稳定之外,Spring 如此出名的原因是 SpringSource 的人编写了许多 POJO,有助于将 Spring 与许多其他常见的集成框架,而不会侵入您的应用程序。此外,Spring 有几个不错的子项目,如 Spring MVC、Spring WebFlow、Spring Security 以及一大堆等等。
希望这会有所帮助。无论如何,我鼓励您阅读 Martin Fowler's article 关于依赖注入和控制反转的内容,因为他比我做得更好。 了解基础知识后看看Spring Documentation,在我看来,它 曾经是有史以来最好的Spring书籍。 p>