Dependency Injection Styles

53,192 views
53,009 views

Published on

"Dependency Injection Styles" by Chris Beams. Spring User Group France, 2010-06-10.

Published in: Technology, Education
2 Comments
12 Likes
Statistics
Notes
No Downloads
Views
Total views
53,192
On SlideShare
0
From Embeds
0
Number of Embeds
67
Actions
Shares
0
Downloads
1,993
Comments
2
Likes
12
Embeds 0
No embeds

No notes for slide

Dependency Injection Styles

  1. 1. DI Styles: Choosing the Right Tool for the Job Chris Beams, Senior Technical Staff, SpringSource CONFIDENTIAL © 2010 SpringSource, A division of VMware. All rights reserved
  2. 2. Hello!  Chris Beams • Senior Staff Engineer with SpringSource • Member Core Spring team • Trained hundreds to use Spring effectively • Author of the forthcoming Spring in a Nutshell (O'Reilly) CONFIDENTIAL 2
  3. 3. Dependency Injection: Simple, Right? TransferService AccountRepository public TransferService(AccountRepository ar) { this.accountRepository = ar; } CONFIDENTIAL 3
  4. 4. Choices @Configuration @Autowired <context:annotation-config/> @Bean <context:component-scan/> @Inject @Component @Configurable <bean/> ... CONFIDENTIAL 4
  5. 5. Agenda  A brief history of Dependency Injection (DI)  Seven characteristics of a DI style  A demo-centric tour of Spring DI styles • Comparative analysis of available styles • What's new in Spring 3 for DI • Demo sources available at: • http://github.com/cbeams/distyles CONFIDENTIAL 5
  6. 6. Agenda  A brief history of Dependency Injection (DI)  Seven characteristics of a DI style  A demo-centric tour of Spring DI styles • Comparative analysis of available styles • What's new in Spring 3 for DI • Demo sources available at: • https://src.springsource.org/svn/springone2gx/distyles CONFIDENTIAL 6
  7. 7. Agenda  A brief history of Dependency Injection (DI)  Seven characteristics of a DI style  A demo-centric tour of Spring DI styles • Comparative analysis of available styles • What's new in Spring 3 for DI • Demo sources available online • http://github.org/cbeams/distyles CONFIDENTIAL 7
  8. 8. A one-slide history of DI  2000: Fowler, et al coin 'POJO'  2002: Johnson, et al: 1:1 J2EE; J2EE w/o EJB  2002-3: Spring and other 'lightweight IoC containers' emerge  2004: Fowler coins 'Dependency Injection as a specialization of the Inversion of Control principle' • Defined three 'types' of DI • Constructor Injection • Setter Injection • Interface Injection  2004-present: Spring evolves; DI is widely adopted CONFIDENTIAL 8
  9. 9. DI: Why?  Dependency Injection enables 'POJO programming'  POJO programming facilitates • Simplicity • Effective separation of concerns • Proper unit testing  Well-factored and well-tested code • Tends to be well-designed code • Evolves well into maintainable systems CONFIDENTIAL 9
  10. 10. DI: Where to Inject?  Three possible 'Injection Points' • Constructor • Good for mandatory dependencies • Setter • Good for optional dependencies • Field • Good for injecting system test fixtures in JUnit tests CONFIDENTIAL 10
  11. 11. DI: How to Configure?  Styles for expressing DI metadata and instructions • External • Configuration files (XML, properties, ...) • Code (Java) • DSL (Spring XML namespaces, Groovy, ...) • Internal • Annotations embedded within POJOs • Usually requires at least some external configuration CONFIDENTIAL 11
  12. 12. DI: Evolution  We've come a long way since Fowler coined DI  Today developers are faced with many choices • Annotations changed the game • Rise of non-Java languages on the JVM creates new possibilities CONFIDENTIAL 12
  13. 13. DI: Today's Choices  Open-source projects • Spring • Grails BeanBuilder • Google Guice • Many other projects across languages  Standards efforts • JSR-250 (Common Annotations) • JSR-299 (Java Contexts and Dependency Injection) • JSR-330 (Dependency Injection for Java) • OSGi 4.2 Blueprint Container CONFIDENTIAL 13
  14. 14. Choosing a DI Style CONFIDENTIAL 14
  15. 15. DI Configuration: What matters to you?  Let's begin by defining the characteristics that matter when thinking about DI  Provide a framework for making decisions about your own applications CONFIDENTIAL 15
  16. 16. Seven Characteristics of a DI Style 1.External vs. Internal 2.Explicit vs. Implicit 3.Type-safety 4.Noninvasiveness 5.Portability (of POJOs) 6.Configurability of 3rd party components 7.Tooling support CONFIDENTIAL 16
  17. 17. Characteristic 1: External vs. Internal External <bean id=“transferService” class=“com.bank.TransferServiceImpl”> <constructor-arg ref=“accountRepository” /> </bean> Internal @Component public class TransferServiceImpl implements TransferService { @Autowired public TransferServiceImpl(AccountRepository repo) { this.accountRepository = repo; } … } CONFIDENTIAL 17
  18. 18. Characteristic 1: External vs. Internal  External DI is noninvasive • But causes context-switching during coding • More verbose • Provides a 'blueprint' of your application  Internal DI is necessarily invasive • May or may not be portable • But requires less coding and maintenance • Easier to use during development CONFIDENTIAL 18
  19. 19. Seven Characteristics of a DI Style 1.External vs. Internal 2.Explicit vs. Implicit 3.Type-safety 4.Noninvasiveness 5.Portability (of POJOs) 6.Configurability of 3rd party components 7.Tooling support CONFIDENTIAL 19
  20. 20. Characteristic 2: Explicit vs. Implicit <bean id=“transferService” class=“com.bank.TransferServiceImpl”> <constructor-arg ref=“accountRepository” /> <constructor-arg ref=“feePolicy” /> </bean> <bean id=“accountRepository” class=“com.bank.JdbcAccountRepository”> <bean id=“feePolicy” class=“com.bank.FlatFeePolicy”> public class TransferServiceImpl implements TransferService { public TransferServiceImpl(AccountRepository accountRepository, FeePolicy feePolicy) { … } … } CONFIDENTIAL 20
  21. 21. Characteristic 2: Explicit vs. Implicit <context:component-scan base-package=“com.bank"> @Component public class TransferServiceImpl implements TransferService { @Autowired public TransferServiceImpl(AccountRepository accountRepository, FeePolicy feePolicy) { … } … } @Component public class JdbcAccountRepository implements AccountRepository{ … } @Component public class FlatFeePolicy implements FeePolicy{ … } CONFIDENTIAL 21
  22. 22. Characteristic 2: Explicit vs. Implicit  Explicit DI comes with greater verbosity • More tedious in simple cases • Easier and more clear when things get complicated  Implicit DI introduces the possibility of ambiguity • If multiple implementations of a given type are detected / scanned • Disambiguation strategies are required • But ambiguities may arise at any time CONFIDENTIAL 22
  23. 23. Explicit vs. Implicit: Ambiguity <context:component-scan base-package=“com.bank"> @Component public class TransferServiceImpl implements TransferService { @Autowired public TransferServiceImpl(AccountRepository accountRepository, FeePolicy feePolicy) { … } … } @Component public class JdbcAccountRepository implements AccountRepository{ … } @Component public class FlatFeePolicy implements FeePolicy{ … } Which one should get @Component injected? public class VariableFeePolicy implements FeePolicy{ … } CONFIDENTIAL 23
  24. 24. Implicit DI: Disambiguation <context:component-scan base-package=“com.bank"> @Component public class TransferServiceImpl implements TransferService { @Autowired public TransferServiceImpl(AccountRepository repo, @Qualifer(“domestic”) FeePolicy feePolicy) { … } … } @Component public class JdbcAccountRepository implements AccountRepository{ … } @Component @Qualifier(“domestic”) public class FlatFeePolicy implements FeePolicy{ … } @Component(“international”) public class VariableFeePolicy implements FeePolicy{ … } CONFIDENTIAL 24
  25. 25. Seven Characteristics of a DI Style 1.External vs. Internal 2.Explicit vs. Implicit 3.Type-safety 4.Noninvasiveness 5.Portability (of POJOs) 6.Configurability of 3rd party components 7.Tooling support CONFIDENTIAL 25
  26. 26. Characteristic 3: Type-safety  XML is inherently not type-safe • Tooling can mitigate this • STS/IDEA/NetBeans are Spring XML-aware and can raise warnings and errors at development time  How can one get the compiler to catch errors in DI configuration? • Custom @Qualifier annotations • @Configuration classes CONFIDENTIAL 26
  27. 27. Seven Characteristics of a DI Style 1.External vs. Internal 2.Explicit vs. Implicit 3.Type-safety 4.Noninvasiveness 5.Portability (of POJOs) 6.Configurability of 3rd party components 7.Tooling support CONFIDENTIAL 27
  28. 28. Characteristic 4: (Non)invasiveness  Originally, noninvasiveness was a defining characteristic of DI and POJO programming  Noninvasiveness matters because • An object should be usable independent of its environment and context • Especially important when it comes to testing  But... • Annotations changed this CONFIDENTIAL 28
  29. 29. Annotations and Invasiveness  Annotations, by definition, are invasive • Requires modifying POJOs  But we may say they are minimally invasive • Because annotations have no detrimental effect on the utility of a POJO • Java 6 even allows for annotations to be missing from the classpath at runtime  Non-standard annotations still impact portability CONFIDENTIAL 29
  30. 30. Seven Characteristics of a DI Style 1.External vs. Internal 2.Explicit vs. Implicit 3.Type-safety 4.Noninvasiveness 5.Portability (of POJOs) 6.Configurability of 3rd party components 7.Tooling support CONFIDENTIAL 30
  31. 31. Characteristic 5: Portability  Ideally, a POJO should be reusable across DI frameworks  Non-standard annotations tie you to a particular framework • Hence the desire for standardization • JSR-330! CONFIDENTIAL 31
  32. 32. Seven Characteristics of a DI Style 1.External vs. Internal 2.Explicit vs. Implicit 3.Type-safety 4.Noninvasiveness 5.Portability (of POJOs) 6.Configurability of 3rd party components 7.Tooling support CONFIDENTIAL 32
  33. 33. Characteristic 6: Configurability of 3rd Party Components  Internal configuration and 3rd party components don't mix • You can't annotate somebody else's code  External configuration is the only way • Hence a complete DI solution must support both CONFIDENTIAL 33
  34. 34. Seven Characteristics of a DI Style 1.External vs. Internal 2.Explicit vs. Implicit 3.Type-safety 4.Noninvasiveness 5.Portability (of POJOs) 6.Configurability of 3rd party components 7.Tooling support CONFIDENTIAL 34
  35. 35. Characteristic 7: Tooling Support  Natural, integrated refactoring • XML-driven DI requires Spring-aware tooling • Code-driven DI takes advantage of built-in IDE Java tooling  Content Assist in configuration files • Generic XML tooling only gets you so far • Need XML tooling built to purpose  Visualization • Seeing the 'blueprint' of your application  Other concerns • Static analysis • Obfuscation CONFIDENTIAL 35
  36. 36. SpringSource Tool Suite (STS) CONFIDENTIAL 36
  37. 37. A Tour of DI Styles CONFIDENTIAL 37
  38. 38. DI Styles  XML • <beans/> • <namespace:*/>  @Autowired  @Configuration  Standards • JSR-250 (Common Annotations) • JSR-299 (Java Contexts and Dependency Injection) • JSR-330 (Dependency Injection for Java) CONFIDENTIAL 38
  39. 39. DI Styles  Remember... • DI styles need not be mutually exclusive! • You'll probably use more than one in a given app CONFIDENTIAL 39
  40. 40. <beans/> CONFIDENTIAL 40
  41. 41. <beans/> XML  The original DI style for Spring  Remains very widely used  General-purpose, thus very powerful  But can get verbose / maintenance-intensive CONFIDENTIAL 41
  42. 42. <beans/> demo CONFIDENTIAL 42
  43. 43. <beans/>: Summary 1.External vs. Internal: External 2.Explicit vs. Implicit: Explicit 3.Type-safe: No 4.Noninvasive: Yes 5.Portable: Yes 6.Can configure 3rd party components: Yes 7.Has tooling support: Yes CONFIDENTIAL 43
  44. 44. <namespace:*/> CONFIDENTIAL 44
  45. 45. <namespace:*/> XML  Introduced in Spring 2.0  Expanded in Spring 2.5 and 3.0  Widely supported by Spring projects • Spring Integration • Spring Batch • Spring Web Flow • Spring Security • ...  Greatly reduces XML verbosity  More expressive at the same time CONFIDENTIAL 45
  46. 46. <namespace:*/> demo CONFIDENTIAL 46
  47. 47. <namespace:*/>: Summary  Same fundamental characteristics as <beans/>  But eliminates much of the verbosity problem with XML • Serves as a 'configuration DSL'  Not just about DI • Helps manage many other aspects of the application • Scheduling, AOP, security, etc. CONFIDENTIAL 47
  48. 48. @Autowired CONFIDENTIAL 48
  49. 49. @Autowired  AKA "Annotation-driven injection"  Introduced in Spring 2.5  More annotations added in Spring 3.0 • @Primary • @Lazy • @DependsOn • extended semantics for @Scope  Widely used today  Works in conjunction with @Component and <context:component- scan/> to streamline development lifecycle CONFIDENTIAL 49
  50. 50. @Autowired demo CONFIDENTIAL 50
  51. 51. @Autowired: Summary 1.External vs. Internal: Internal 2.Explicit vs. Implicit: Implicit 3.Type-safe: Yes 4.Noninvasive: No 5.Portable: No 6.Can configure 3rd party components: No 7.Has tooling support: Yes (as of STS 2.2.0) CONFIDENTIAL 51
  52. 52. JSR-330 (@Inject) CONFIDENTIAL 52
  53. 53. Introducing JSR-330  AKA @Inject  A joint JCP effort by Google and SpringSource  Provides common understanding of injection semantics through portable DI annotations  Packaged under javax.inject.* (Java SE)  JSR went final late 2009 • API is available in Maven Central  Spring 3.0 GA passes the TCK CONFIDENTIAL 53
  54. 54. Smallest. JSR. Ever. CONFIDENTIAL 54
  55. 55. JSR-330 demo CONFIDENTIAL 55
  56. 56. JSR-330: Summary 1.External vs. Internal: Internal 2.Explicit vs. Implicit: Undefined! (can be either) 3.Type-safe: Yes 4.Noninvasive: No 5.Portable: Yes 6.Can configure 3rd party components: No 7.Has tooling support: Yes (STS) CONFIDENTIAL 56
  57. 57. @Autowired and @Inject: The Bottom Line  JSR-330 standardizes internal DI annotations • Meaning: portable POJOs  However, @Inject is a subset of the functionality provided by Spring's @Autowired support  Rule of thumb • You can get 80% of what you need with @Inject • Rely on @Autowired and friends for the rest CONFIDENTIAL 57
  58. 58. From @Autowired to @Inject Spring javax.inject.* @Autowired @Inject * @Inject has no 'required' attribute @Component @Named * Spring supports scanning for @Named @Scope @Scope * for meta-annotation and injection points only @Scope @Singleton * jsr-330 default scope is like Spring's 'prototype' ("singleton") @Qualifier @Qualifier, @Named @Value no equivalent see SPR-6251 for ideas on how Spring can help bridge this gap @Primary no equivalent @Lazy no equivalent @Required no equivalent CONFIDENTIAL 58
  59. 59. @Configuration CONFIDENTIAL 59
  60. 60. @Configuration  Formely Spring JavaConfig  Now included in core Spring Framework 3.0  Annotation-driven, but is an external DI style • POJOs remain untouched by annotations  Provides full programmatic control over object instantiation and DI  Allows for object-oriented configuration  Integrates well with other Spring DI styles CONFIDENTIAL 60
  61. 61. A @Configuration class @Configuration public class AppConfig { @Bean public TransferService transferService() { return new TransferService(accountRepository()); } @Bean public AccountRepository accountRepository() { return new JdbcAccountRepository(dataSource()); } // ... } CONFIDENTIAL 61
  62. 62. Look familiar? <bean id=“transferService” class=“com.bank.TransferServiceImpl”> <constructor-arg ref=“accountRepo” /> </bean> <bean id=“accountRepo” class=“com.bank.JdbcAccountRepository”> <constructor-arg ref=“dataSource” /> </bean> CONFIDENTIAL 62
  63. 63. Bootstrapping @Configuration public class CommandLineApplication { public static void main(String... args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); TransferService transferService = ctx.getBean(TransferService.class); transferService.transfer(100.00, “A123”, “C456”); } } CONFIDENTIAL 63
  64. 64. @Configuration demo CONFIDENTIAL 64
  65. 65. @Configuration: Summary 1.External vs. Internal: External 2.Explicit vs. Implicit: Explicit 3.Type-safe: Yes 4.Noninvasive: Yes 5.Portable: Yes 6.Can configure 3rd party components: Yes 7.Has tooling support: Yes CONFIDENTIAL 65
  66. 66. Spring is about choice  Choice in many areas...  All DI metadata (internal or external) contributes to the core BeanDefinition model • This layer is what makes adding different configurations styles possible!  Spring embraces any relevant deployment environment • Use latest DI/EE6 styles on • J2EE 1.5 and JEE 5 • OSGi CONFIDENTIAL 66
  67. 67. Q&A CONFIDENTIAL 67
  68. 68. Thank you! https://github.com/cbeams/distyles http://twitter.com/cbeams CONFIDENTIAL 68
  69. 69. Groovy/Grails BeanBuilder CONFIDENTIAL 69
  70. 70. BeanBuilder  DSL for creating Spring BeanDefinitions  Currently part of Grails  Work is underway to include within Spring 3.1 CONFIDENTIAL 70
  71. 71. Grails BeanBuilder at a Glance import org.springframework.context.ApplicationContext import grails.spring.BeanBuilder ... def bb = new BeanBuilder() bb.beans { transferService(TransferServiceImpl, accountRepository, feePolicy) accountRepository(JdbcAccountRepository, dataSource) dataSource(BasicDataSource) { driverClassName = "org.hsqldb.jdbcDriver" url = "jdbc:hsqldb:mem:grailsDB" username = "sa" password = "" } } ApplicationContext ctx = bb.createApplicationContext(); TransferService transferService = ctx.getBean(TransferService); CONFIDENTIAL 71
  72. 72. @Configuration: Summary 1.External vs. Internal: External 2.Explicit vs. Implicit: Explicit 3.Type-safe: No 4.Noninvasive: Yes 5.Portable: Yes 6.Can configure 3rd party components: Yes 7.Has tooling support: No CONFIDENTIAL 72

×