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. 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
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. 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. 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. 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. 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. 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. 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. 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. 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
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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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
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
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
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
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
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
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
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. @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. 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
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. A @Configuration class
@Configuration
public class AppConďŹg {
@Bean
public TransferService transferService() {
return new TransferService(accountRepository());
}
@Bean
public AccountRepository accountRepository() {
return new JdbcAccountRepository(dataSource());
}
// ...
}
CONFIDENTIAL 61
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. 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
70. BeanBuilder
ď§ DSL for creating Spring BeanDefinitions
ď§ Currently part of Grails
ď§ Work is underway to include within Spring 3.1
CONFIDENTIAL 70