CSC/ECE 517 Fall 2010/ch5 5e ms: Difference between revisions
No edit summary |
|||
(12 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
Dependency Injection | ==Dependency Injection== | ||
Java applications typically consist of objects that collaborate with each to form a proper application. Thus the objects in an application have dependencies on each other. | Java applications typically consist of objects that collaborate with each to form a proper application. Thus the objects in an application have dependencies on each other. | ||
Line 5: | Line 5: | ||
Dependency injection is way of providing the objects that it needs ie the dependencies that are needed instead of having it construct the dependencies by itself. Dependencies can injected in many ways either by using a specialized dependency injection frameworks like Spring or Google Guice or could be injected simply by instantiating and passing objects (dependencies) explicitly. | Dependency injection is way of providing the objects that it needs ie the dependencies that are needed instead of having it construct the dependencies by itself. Dependencies can injected in many ways either by using a specialized dependency injection frameworks like Spring or Google Guice or could be injected simply by instantiating and passing objects (dependencies) explicitly. | ||
==Example== | |||
[[Image:DependencyInjection.jpg]] | |||
Uses of Dependency Injection: | ==Types of Dependency Injection== | ||
1.Construction Injection | |||
2.Setter Injection | |||
==Uses of Dependency Injection:== | |||
It's a very useful technique for testing, since it allows dependencies to be mocked or stubbed out. Simplies testing and improves decoupling. | It's a very useful technique for testing, since it allows dependencies to be mocked or stubbed out. Simplies testing and improves decoupling. | ||
==Construtor Injection:== | |||
Construtor Injection: | |||
The basic idea with constructor-injection is that the object has no defaults and instead you have a single constructor where all of the collaborators and values need to be supplied before you can instantiate the object. | The basic idea with constructor-injection is that the object has no defaults and instead you have a single constructor where all of the collaborators and values need to be supplied before you can instantiate the object. | ||
Lets start how injection is done using light weight container called Google guice | Lets start how injection is done using light weight container called Google guice | ||
class RealBillingService implements BillingService { | class RealBillingService implements BillingService { | ||
Line 27: | Line 31: | ||
this.transactionLog = transactionLog; | this.transactionLog = transactionLog; | ||
} | } | ||
} | |||
} | |||
We want to build a RealBillingService using PaypalCreditCardProcessor and DatabaseTransactionLog. Guice uses bindings to map types to their implementations. | We want to build a RealBillingService using PaypalCreditCardProcessor and DatabaseTransactionLog. Guice uses bindings to map types to their implementations. | ||
Line 56: | Line 59: | ||
*/ | */ | ||
Injector injector = Guice.createInjector(new BillingModule()); | Injector injector = Guice.createInjector(new BillingModule()); | ||
/* | /* | ||
* Now that we've got the injector, we can build objects. | * Now that we've got the injector, we can build objects. | ||
Line 64: | Line 66: | ||
} | } | ||
Advantage of having a constructor injection is it enforces order of initialization and prevents circular dependencies | Advantage of having a constructor injection is it enforces order of initialization and prevents circular dependencies. | ||
Setter Injection | ==Setter Injection== | ||
It is that you have a no argument-constructor which creates the object with "reasonable-defaults" . The user of the object can then call setters on the object to override the collaborators of the object in order to wire the object graph together or to replace the key collaborators with test-doubles. | It is that you have a no argument-constructor which creates the object with "reasonable-defaults" . The user of the object can then call setters on the object to override the collaborators of the object in order to wire the object graph together or to replace the key collaborators with test-doubles. | ||
Line 74: | Line 75: | ||
class RealBillingService implements BillingService { | class RealBillingService implements BillingService { | ||
private final CreditCardProcessor processor; | private final CreditCardProcessor processor; | ||
public void setCreditCardProcessor(CreditCardProcessor processor){ | public void setCreditCardProcessor(CreditCardProcessor processor){ | ||
this.processor = processor | |||
} | } | ||
} | } | ||
class PaypalCreditCardProcessor{ | class PaypalCreditCardProcessor{ | ||
public void setPayPalAccount(Account account){ | |||
this.account =account; | |||
} | |||
} | } | ||
The next step is to set up the configuration for the files. Spring supports configuration through XML files and also through code, but XML is the expected way to do it. | The next step is to set up the configuration for the files. Spring supports configuration through XML files and also through code, but XML is the expected way to do it. | ||
Line 111: | Line 109: | ||
assertEquals("Once Upon a Time in the West", product.getTitle()); | assertEquals("Once Upon a Time in the West", product.getTitle()); | ||
} | } | ||
==References== | |||
1. MartinFowler. ''Inversion of Control Containers and the Dependency Injection pattern''[http://www.martinfowler.com/articles/injection.html#ANaiveExample] | |||
2. Google Guice[http://code.google.com/p/google-guice/wiki/GettingStarted] | |||
3. Rod Johnson. ''Introduction to the Spring Framework'' [http://www.theserverside.com/news/1364527/Introduction-to-the-Spring-Framework] |
Latest revision as of 17:29, 4 November 2010
Dependency Injection
Java applications typically consist of objects that collaborate with each to form a proper application. Thus the objects in an application have dependencies on each other.
Dependency injection is way of providing the objects that it needs ie the dependencies that are needed instead of having it construct the dependencies by itself. Dependencies can injected in many ways either by using a specialized dependency injection frameworks like Spring or Google Guice or could be injected simply by instantiating and passing objects (dependencies) explicitly.
Example
Types of Dependency Injection
1.Construction Injection 2.Setter Injection
Uses of Dependency Injection:
It's a very useful technique for testing, since it allows dependencies to be mocked or stubbed out. Simplies testing and improves decoupling.
Construtor Injection:
The basic idea with constructor-injection is that the object has no defaults and instead you have a single constructor where all of the collaborators and values need to be supplied before you can instantiate the object.
Lets start how injection is done using light weight container called Google guice
class RealBillingService implements BillingService { private final CreditCardProcessor processor; private final TransactionLog transactionLog; @Inject RealBillingService(CreditCardProcessor processor, TransactionLog transactionLog) { this.processor = processor; this.transactionLog = transactionLog; } }
We want to build a RealBillingService using PaypalCreditCardProcessor and DatabaseTransactionLog. Guice uses bindings to map types to their implementations.
public class BillingModule extends AbstractModule { @Override protected void configure() { /* * This tells Guice that whenever it sees a dependency on a TransactionLog, * it should satisfy the dependency using a DatabaseTransactionLog. */ bind(TransactionLog.class).to(DatabaseTransactionLog.class); /* * Similarly, this binding tells Guice that when CreditCardProcessor is used in * a dependency, that should be satisfied with a PaypalCreditCardProcessor. */ bind(CreditCardProcessor.class).to(PaypalCreditCardProcessor.class); }
} The modules are the building blocks of an injector, which is Guice's object-graph builder. First we create the injector, and then we can use that to build the RealBillingService:
public static void main(String[] args) { /* * Guice.createInjector() takes your Modules, and returns a new Injector * instance. Most applications will call this method exactly once, in their * main() method. */ Injector injector = Guice.createInjector(new BillingModule()); /* * Now that we've got the injector, we can build objects. */ RealBillingService billingService = injector.getInstance(RealBillingService.class); ... }
Advantage of having a constructor injection is it enforces order of initialization and prevents circular dependencies.
Setter Injection
It is that you have a no argument-constructor which creates the object with "reasonable-defaults" . The user of the object can then call setters on the object to override the collaborators of the object in order to wire the object graph together or to replace the key collaborators with test-doubles.
class RealBillingService implements BillingService { private final CreditCardProcessor processor; public void setCreditCardProcessor(CreditCardProcessor processor){ this.processor = processor } } class PaypalCreditCardProcessor{ public void setPayPalAccount(Account account){ this.account =account; } }
The next step is to set up the configuration for the files. Spring supports configuration through XML files and also through code, but XML is the expected way to do it.
<beans> <bean id="RealBillingService" class="spring.RealBillingService"> <property name="processor"> <ref local="CreditCardProcessor"/> </property> </bean> <bean id="CreditCardProcessor" class="spring.PaypalCreditCardProcessor"> <property name="account"> <value>1001</value> </property> </bean> </beans>
A simple test as follows
public void testWithSpring() throws Exception { ApplicationContext ctx = new FileSystemXmlApplicationContext("spring.xml"); RealBillingService service = (RealBillingService) ctx.getBean("RealBillingService"); Products[] product = service.buyProduct("100"); // Argument is the amount to be debited for the purchase of products. assertEquals("Once Upon a Time in the West", product.getTitle()); }
References
1. MartinFowler. Inversion of Control Containers and the Dependency Injection pattern[1]
2. Google Guice[2]
3. Rod Johnson. Introduction to the Spring Framework [3]