by Google Apache 2.0 license All configuration in code Type-safe. Supports generics and annotations Guice does approximately one sixth of what Spring does (IoC and AOP), . . . but it does its small part well, . . . and without all the XML
to achieve the software architecture principle Inversion of Control (IoC) .NET typically uses the S L pattern Another way, popular in Java, is the F pattern
c e BillingService { / * * * Attempts to charge the order to the c r e d i t card . Both * successful and f a i l e d transactions w i l l be recorded . * * @return a receipt of the transaction . I f the charge was * successful , the receipt w i l l be successful . Otherwise , the * receipt w i l l contain a decline note describing why the * charge f a i l e d . * / Receipt chargeOrder ( PizzaOrder order , CreditCard creditCard ) ; } Examples taken (and slightly modified) from http://code.google.com/p/google-guice/wiki/Motivation
public class CreditCardProcessorFactory { private s t a t i c CreditCardProcessor instance ; public s t a t i c void setInstance ( CreditCardProcessor ← creditCardProcessor ) { instance = creditCardProcessor ; } public s t a t i c CreditCardProcessor getInstance ( ) { i f ( instance == n u l l ) { throw new IllegalStateException ( " CreditCardProcessorFactory not i n i t i a l i z e d . " + " Did you forget to c a l l setInstance ( ) ?" ) ; } return instance ; } }
test case. public class RealBillingServiceTest { / / . . . f i e l d s here . . . @Before public void setUp ( ) { TransactionLogFactory . setInstance ( inMemoryTransactionLog ) ; CreditCardProcessorFactory . setInstance ( fakeCreditCardProcessor ) ; } @After public void tearDown ( ) { TransactionLogFactory . setInstance ( n u l l ) ; CreditCardProcessorFactory . setInstance ( n u l l ) ; } / / . . . tests here . . . }
f i n a l CreditCardProcessor processor ; private f i n a l TransactionLog transactionLog ; public RealBillingService ( CreditCardProcessor processor , TransactionLog transactionLog ) { t h i s . processor = processor ; t h i s . transactionLog = transactionLog ; } public Receipt chargeOrder ( PizzaOrder order , CreditCard ← creditCard ) { ChargeResult result = processor . charge ( creditCard , order . ← getAmount ( ) ) ; transactionLog . logChargeResult ( result ) ; / / . . . } }
. . private f i n a l InMemoryTransactionLog transactionLog = new InMemoryTransactionLog ( ) ; private f i n a l FakeCreditCardProcessor creditCardProcessor = new FakeCreditCardProcessor ( ) ; @Test public void successfulCharge ( ) { RealBillingService billingService = new RealBillingService ( creditCardProcessor , transactionLog ) ; Receipt receipt = billingService . chargeOrder ( order , ← creditCard ) ; assertTrue ( receipt . hasSuccessfulCharge ( ) ) ; } }
what implementation to use for each interface. public class BillingModule extends AbstractModule { @Override protected void configure ( ) { bind ( TransactionLog . class ) . to ( DatabaseTransactionLog . class ) ; bind ( CreditCardProcessor . class ) . to ( PaypalCreditCardProcessor . class ) ; bind ( BillingService . class ) . to ( RealBillingService . class ) ; } } If you only have one implementation in your class path, Guice will choose that one for you automatically.
private f i n a l CreditCardProcessor processor ; private f i n a l TransactionLog transactionLog ; @Inject public RealBillingService ( CreditCardProcessor processor , TransactionLog transactionLog ) { t h i s . processor = processor ; t h i s . transactionLog = transactionLog ; } public Receipt chargeOrder ( PizzaOrder order , CreditCard ← creditCard ) { ChargeResult result = processor . charge ( creditCard , order . ← getAmount ( ) ) ; transactionLog . logChargeResult ( result ) ; / / . . . } }
and ask it for an instance of any interface or class which Guice has bound to an implementation. public s t a t i c void main ( String [ ] args ) { Injector injector = Guice . createInjector (new BillingModule ( ) ) ; BillingService billingService = injector . getInstance (← BillingService . class ) ; / / . . . }
setter injection (@Inject the setter) field injection (@Inject the field) binding to instances creating new instances whenever needed (default) reusing instances within a unit of work (e.g. HTTP request) reusing instances forever (singletons) providing short-lived instances to more long-lived objects through Providers and more . . .
and its dependencies Move the decision of what implementation of a dependency to use out of the consuming code Move the responsibility of managing the life cycle of dependencies from the consumer to a dependency injector Improve testability Reduce the amount of boilerplate code for creating objects Boilerplate means tedious Tedious means error prone
“somewhere else” may seem “magic” to some developers Needs to understand both the configuration and the code to understand the application The configuration is often in XML, which usually means that you have to maintain it manually when refactoring But not in Guice
at http://www.wideplay.com/guicewebextensions2 JUnit test runner with Guice support? http://cowwoc.blogspot.com/2008/10/ integrating-google-guice-into-junit4.html