Professional Documents
Culture Documents
CHP 2 - Dependency Injection Using Spring Rev H PDF
CHP 2 - Dependency Injection Using Spring Rev H PDF
Injection Using
Spring
Introducing the Spring Application Context
and Spring's Java Configuration capability
2-1 02-cs-javaconfig-di - 1
How Spring Works
Your Application Classes
(POJOs)
Spring
Configuration
ApplicationContext
Instructions
Creates
Fully configured
application system
Ready for use
2-2 02-cs-javaconfig-di - 2
Configuration Instructions
2-3 02-cs-javaconfig-di - 3
Accessing a Bean
• Multiple ways
ApplicationContext context = SpringApplication.run(...);
Application Context
transferService
TransferServiceImpl
accountRepository
JdbcAccountRepository
dataSource
BasicDataSource
2-4 02-cs-javaconfig-di - 4
Bean Descriptions
@Bean
@Description("Handles all transfer related use-cases")
public TransferService transferService() { … }
@Bean
@Description("Provides access to data from the Accounts table")
public AccountRepository accountRepository() { … }
@Bean
@Description("Data-source for the underlying RDB we are using")
public DataSource dataSource() { … }
2-5 02-cs-javaconfig-di - 5
Topics in this session
2-6 02-cs-javaconfig-di - 6
Application Context Example
Instantiating Within a System (Integration) Test
public class TransferServiceTests {
private TransferService service;
Bootstraps the
@Before public void setUp() { system to test
// Create the application from the configuration
ApplicationContext context =
SpringApplication.run( ApplicationConfig.class )
// Look up the application service interface
service = context.getBean(TransferService.class);
}
2-7 02-cs-javaconfig-di - 7
Creating an Application Context from
Multiple Files
• Your @Configuration class can get very long
– Instead use multiple files combined with @Import
– Defines a single Application Context
• With beans sourced from multiple files
@Configuration
@Import({InfrastructureConfig.class, WebConfig.class })
public class ApplicationConfig {
...
}
@Configuration @Configuration
public class InfrastructureConfig { public class WebConfig {
... ...
} }
Datasource infra-structure
Datasource
2-8 02-cs-javaconfig-di - 8
Mixed Configuration
application beans
Coupled to a
local Postgres
environment
infrastructure bean
Partitioning Configuration
@Configuration application beans
public class ApplicationConfig {
@Autowired DataSource dataSource;
2-9 02-cs-javaconfig-di - 9
Referencing Beans Defined in Another File
2 - 10 02-cs-javaconfig-di - 10
… But Avoid “Tramp Data”
@Configuration
Bad: dataSource is a “tramp”!
@Import( InfrastructureConfig.class )
public class ApplicationConfig {
@Bean public AccountService accountService( DataSource dataSource ) {
return new accountService( accountRepository(dataSource) ); tramp
} tramp
@Bean public AccountService accountRepository( DataSource dataSource ) {
return new accountRepository( dataSource );
}
} @Configuration
@Import( InfrastructureConfig.class ) Better: Pass actual dependency
public class ApplicationConfig {
@Bean public AccountService accountService( AccountRepository repo ) {
return new accountService( repo );
}
@Bean public AccountService accountRepository( DataSource ds ) {
return new accountRepository( ds );
}
}
2 - 11 02-cs-javaconfig-di - 11
Topics in this session
service1 == service2
Bean Scope: default
2 - 12 02-cs-javaconfig-di - 12
service1 != service2
Bean Scope: prototype
• Scope "prototype"
– New instance created every time bean is referenced
@Bean
@Scope(scopeName=“prototype”)
@Scope(“prototype”)
public AccountService accountService() {
return …
}
2 - 13 02-cs-javaconfig-di - 13
Other Scopes
2 - 14 02-cs-javaconfig-di - 14
Lab 2
Javaconfig-dependency-injection
2 - 15 02-cs-javaconfig-di - 15
Dependency
Injection Using
Spring 2
Deeper Look into Spring's Java
Configuration Capability
• External Properties
• Profiles
• Spring Expression Language
• Proxying
2 - 16 03-cs-javaconfig-di2 - 1
Setting property values
2 - 17 03-cs-javaconfig-di2 - 2
Spring's Environment Abstraction – 2
@Configuration
public class DbConfig { Property names
private static final String DB_DRIVER = "db.driver";
private static final String DB_URL = "db.url";
private static final String DB_USER = "db.user";
private static final String DB_PWD = "db.password";
Property Sources
@Configuration
@PropertySource ( “classpath:/com/organization/config/app.properties” )
@PropertySource ( “file:config/local.properties” )
public class ApplicationConfig {
...
} Adds properties from these files in addition to
environment variables and system properties
2 - 18 03-cs-javaconfig-di2 - 3
Accessing Properties using @Value
@Configuration Convenient
public class DbConfig { alternative to
explicitly using
@Bean Environment
public DataSource dataSource(
@Value("${db.driver}") String driver,
@Value("${db.url}") String url,
@Value("${db.user}") String user,
@Value("${db.password}") String pwd) {
DataSource ds = new BasicDataSource();
ds.setDriverClassName( driver);
ds.setUrl( url);
ds.setUser( user);
ds.setPassword( pwd ));
return ds;
}
} BUT: How are these ${...} variables resolved? Next slide ...
@Bean
public static PropertySourcesPlaceholderConfigurer pspc() {
return new PropertySourcesPlaceholderConfigurer();
}
${..} placeholders are not resolved unless this bean declared
2 - 19 03-cs-javaconfig-di2 - 4
${...} Placeholders
db.driver=org.postgresql.Driver
db.url=jdbc:postgresql://localhost/transfer
db.user=transfer-app
db.password=secret45 db.driver=org.postgresql.Driver
db.url=jdbc:postgresql://qa/transfer
app-dev.properties app-prod.properties
db.user=transfer-app
db.password=secret88
app-qa.properties
• External Properties
• Profiles
• Spring Expression Language
• Proxying
2 - 20 03-cs-javaconfig-di2 - 5
Profiles
• Beans can be grouped into Profiles
– Profiles can represent purpose: “web”, “offline”
– Or environment: “dev”, “qa”, “uat”, “prod”
– Beans included / excluded based on profile membership
ApplicationContext
Beans with Transfer Account
no profile Service Service web
Customer Account Other
always Repository Error
Repository Other
available Handler
Other
dev
Other
data prod
Source qa data
connection data Source
Factory Source connection
performance connection Factory
Monitor Factory
Defining Profiles – 1
@Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
return builder.setName("testdb")
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:/testdb/schema.db")
.addScript("classpath:/testdb/test-data.db").build();
}
…
2 - 21 03-cs-javaconfig-di2 - 6
Defining Profiles - 2
2 - 22 03-cs-javaconfig-di2 - 7
Quiz:
Which of the Following is/are Selected?
-Dspring.profiles.active=jpa
? ? ?
@Configuration @Configuration @Configuration
public class @Profile("jpa") @Profile("jdbc")
Config { ...} public class public class
JpaConfig JdbcConfig
{ ...} { ...}
db.driver=org.postgresql.Driver
db.url=jdbc:postgresql://localhost/transfer
db.user=transfer-app
db.password=secret45
dev.properties prod.properties
2 - 23 03-cs-javaconfig-di2 - 8
Topics in this session
• External Properties
• Profiles
• Spring Expression Language
• Proxying
2 - 24 03-cs-javaconfig-di2 - 9
SpEL examples – Using @Value
@Configuration
class TaxConfig
{
@Value("#{ systemProperties['user.region'] }") String region;
2 - 25 03-cs-javaconfig-di2 - 10
Accessing Properties
@Value("${daily.limit}") @Value("#{environment['daily.limit']}")
int maxTransfersPerDay; int maxTransfersPerDay;
SpEL
2 - 26 03-cs-javaconfig-di2 - 11
Topics in this session
• External Properties
• Profiles
• Spring Expression Language
• Proxying
Quiz
Which is the best
@Bean implementation?
public AccountRepository accountRepository() {
return new JdbcAccountRepository();
}
@Bean
public TransferService transferService1() {
TransferServiceImpl service = new TransferServiceImpl(); 1. Method call?
service.setAccountRepository(accountRepository());
return service;
}
2. New instance?
@Bean
public TransferService transferService2() {
return new TransferServiceImpl( new JdbcAccountRepository() );
}
Prefer call to dedicated method. Let's discuss why ...
2 - 27 03-cs-javaconfig-di2 - 12
Working with Singletons
@Bean
• public
singleton is the default
AccountRepository scope
accountRepository() {
return new JdbcAccountRepository(); Singleton??
}
@Bean
public TransferService transferService() {
TransferServiceImpl service = new TransferServiceImpl();
service.setAccountRepository(accountRepository()); Method
return service; called twice
} more
@Bean
public AccountService accountService() {
return new AccountServiceImpl( accountRepository() );
}
HOW IS IT POSSIBLE?
2 - 28 03-cs-javaconfig-di2 - 13
Inheritance-based Proxies
Summary
2 - 29 03-cs-javaconfig-di2 - 14