什么是IOC

This article aims to introduce the notion of Inversion Of Control (IoC) and how it can streamline application design. We will look at the different types of IoC frameworks. By showing how IoC can result in simpler, more flexible code, you'll also be able to see why IoC has attracted so much interest of late.
The Theory of IoC
The best way to describe what IoC is about, and what benefits it can provide, is to look at a simple example. The following JDBCDataManger class is used to manage our application's accessing of the database. This application is currently using raw JDBC for persistence. To access the persistence store via JDBC, the JDBCDataManger will need a DataSource object. The standard approach would be to hard code this DataSource object into the class, like this:
public class JDBCDataManger {
public void accessData() {
       DataSource dataSource = new DataSource();
       //access data
       ...
}
Given that JDBCDataManger is handling all data access for our application, hard coding the DataSource isn't that bad, but we may want to further abstract the DataSource , perhaps getting it via some system-wide property object:
public class JDBCDataManger {
public void accessData() {
       DataSource dataSource =
         ApplciationResources.getDataSource();
}
In either case, the JDBCDataManger has to fetch the DataSource itself.
IoC takes a different approach — with IoC, the JDBCDataManger would declare its need for a DataSource and have one provided to it by an IoC framework. This means that the component would no longer need to know how to get the dependency, resulting in cleaner, more focused, and more flexible code.
IoC Frameworks
The ideas behind IoC aren't especially new; in fact, many have remarked that IoC is nothing but a new acronym for the older Dependency Inversion Principle (PDF file). What is new is the interest in IoC, and the large number of frameworks being actively developed to aid the use of IoC.
IoC frameworks are the facilitators for the IoC pattern — think of a framework's job as being the glue for connecting the components in an IoC system. While the general principle of IoC is fairly straightforward, there are several distinct implementations evident in the frameworks. The developers of PicoContainer originally defined the three types of IoC, in order to differentiate their approach from the other frameworks around at the time. At first, these types were simply called Types 1,2, and 3, but in Martin Fowler's recent article, "Inversion of Control Containers and the Dependency Injection Pattern," he coined some more informative terms for these three types, which we will use below.
In the rest of the article, we'll look briefly at Avalon, and in more depth at the two most popular IoC frameworks, Spring and PicoContainer, and the types of IoC they provide.
Interface Injection (Type 1)
With Interface Injection IoC, components implement specific interfaces provided by their containers in order to be configured. Let's look at a refactor of our JDBCDataManager that uses the Avalon framework:
import org.apache.avalon.framework.*;
public class JDBCDataManger implements Serviceable {
       DataSource dataSource;
       public void service (ServiceManager sm)
             throws ServiceException {
         dataSource = (DataSource)sm.lookup("dataSource");
       }
    
       public void getData() {
         //use dataSource for something
       }
}
This form of IoC has been around for longer than the term IoC has been in use — many of you might have used such a form of IoC when using the EJB framework, for example. Here, your components extend and implement specified interfaces, which then get called by the framework itself.
The fact that the Avalon framework has been providing an IoC framework for several years now, without generating nearly as much interest in the idea as either Spring or PicoContainer, is probably due to the downsides of this approach. The requirement to implement specific interfaces can give code a "bloated" feel, while at the same time coupling your application code to the underlying framework. The benefits provided by the other two forms of IoC we will look at next far outweigh those provided by this form of IoC.
Setter Injection (Type 2)
With Setter Injection IoC, some external metadata is used to resolve dependencies. In Spring, this metadata takes the form of an XML configuration file. With this form of IoC, the JDBCDataManager class looks like a normal bean:
public class JDBCDataManger {
private DataSource dataSource;
public void setDataManager(DataSource dataSource {
       this.dataSource = dataSource;
}
public void getData() {
         //use dataSource for something
}
}
Our JDBCDataManger component exposes its dataSource property to allow Spring to set it. Spring does this using its XML configuration. First we define a data source bean (which can be reused by multiple components):
<bean id="myDataSource"
class="org.apache.commons.dbcp.BasicDataSource" >
<property name="driverClassName">
       <value>com.mydb.jdbc.Driver</value>
</property>
<property name="url">
       <value>jdbc:mydb://server:port/mydb</value>
</property>
<property name="username">
       <value>root</value>
</property>
</bean>
Next, we define an instance of our manager and pass in a reference to the data source:
<bean id="dataManager"
class="example.JDBCDataManger">
<property name="dataSource">
       <ref bean="myDataSource"/>
</property>
</bean>
At runtime, a JDBCDataManger class will be instantiated with the correct DataSource dependency resolved, and we will be able to access the bean via the Spring framework itself.
The definition of dependencies in this way makes unit testing a breeze: simply define an XML file for your mock objects, replacing your normal XML file, and away you go.
Perhaps the main advantage of Setter Injection is that application code is not tied to the container in any way, but this is also a downside — it's not immediately clear how this JDBCDataManger component relates to everything else. It almost seems as though the DataSource is being magically passed to the JDBCDataManger , as the dependency management is being done outside of the Java code. Another disadvantage  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值