Advantages of Spring (when used for dependency injection):
- separates configuration from the code. Thus the wiring of the application can be modified without recompiling, in theory. Not sure how often this happens in practice.
... and the cons:
- Xml config files are easy to get wrong (no compile time checks obviously)
- Annotations spread through out the code are not terribly visible
- Error messages thrown by the framework can be cryptic at times
There is a simpler alternative. Do away with the Spring container and inject the dependencies manually. All that is needed is a class to inject the dependency, a context which creates the appropriate dependency, and a bit of application code to wire the two together.- Annotations spread through out the code are not terribly visible
- Error messages thrown by the framework can be cryptic at times
A DbReader uses a constructor-injected datasource to retrieve database results.
class DbReader{
DataSource dataSource;
DbReader (DataSource dataSource){
this.dataSource= dataSource;
}
public Object fetch(){
//use the data source to execute a database query
}
A Context holds a reference to a data source (mock or real)
class Context {
DataSource dataSource;
static Context liveContext(){
//get production db data source
DataSource dataSource = ...;
return new Context(dataSource);
}
static Context mockContext(){
// get in memory test db data source (or mock)
DataSource dataSource = ...;
return new Context(dataSource);
}
Context(DataSource dataSource){
this.dataSource = dataSource;
}
DataSource getDataSource(){
return dataSource;
}
}
Project classes inject the datasource associated with a live context in the DbReader constructor.
public static void main(String args[]){
Context ctx = Context.liveContext();
//fetch data from a prod database
Object result = new DbReader(ctx.getDataSource()).fetch();
}
while integration tests inject a mock datasource from a mock context.:
@Test
public void Test(){
Context ctx = Context.mockContext();
//fetch data from a mock or in-memory db
Object result = new DbReader(ctx.getDataSource()).fetch();
//assert that result is as expected...
}
Simple, easy to understand (and to debug), compile-time checks in place, no messing around with xml configuration files (or annotations).
...and it's even simpler with the Unsprung project which can help generate the Context class above from a Spring configuration file.
No comments:
Post a Comment