预计阅读时间: 7 分钟
在Java社区有一股使用轻量级容器来帮助组装不同项目的组件、集成到一个有凝聚力的应用程序的热潮。
这些底层容器有一种普遍的模式去展示他们如何装配组件,他们提出一个概念,名为“控制反转”( Inversion of Control )。
接下来我们深入挖掘下这个模式在“依赖注入”( Dependency Injection )怎么运作的,并且跟服务定位器进行对比。
我说的使用组件意味着,很多软件能自由的使用它,不需改变,因为这个组件已经不受作者的控制。
当我们在外部系统中使用的时候,服务类似组件。
唯一的不同点是我期望在本地使用组件(eg jar file,assembly,dll,or source inport)。
服务通过远程接口来远程调用,可以同步或者异步操作。(eg web service, messaging system, RPC, or socket.)
分为三种类型:构造器注入、setter注入、接口注入。
1 构造器:
class MovieLister... public MovieLister(MovieFinder finder) { this.finder = finder; }
2 setter:
class MovieLister... private MovieFinder finder; public void setFinder(MovieFinder finder) { this.finder = finder; }
setter的xml配置
<beans> <bean id="MovieLister" class="spring.MovieLister"> <property name="finder"> <ref local="MovieFinder"/> </property> </bean> </beans>
3 接口:
public interface InjectFinder { void injectFinder(MovieFinder finder); } class MovieLister implements InjectFinder public void injectFinder(MovieFinder finder) { this.finder = finder; }
依赖注入最主要的好处是移除了MovieLister和MovieFinder的implementation(实现)上的依赖。但这并不是唯一的方法,另一种方法是服务定位器。
class ServiceLocator... private static ServiceLocator soleInstance; public static void load(ServiceLocator arg) { soleInstance = arg; } private Map services = new HashMap(); public static Object getService(String key){ return soleInstance.services.get(key); } public void loadService (String key, Object service) { services.put(key, service); } class Tester... private void configure() { ServiceLocator locator = new ServiceLocator(); locator.loadService("MovieFinder", new ColonMovieFinder("movies1.txt")); ServiceLocator.load(locator); } class MovieLister... MovieFinder finder = (MovieFinder) ServiceLocator.getService("MovieFinder");
依赖注入对于服务定位器来说是一种备选方案。服务定位器因为它的直接行为而有些许优势,但是如果你在很多应用中创建classes的时候,依赖注入是一种更好的选择。
思考:
4.Separating Configuration from Use
参考文章: http://martinfowler.com/articles/injection.html