Last month I posted about
anemic domain models . Here are some more thoughts, hopefully clarifications with an example that shows the problem and the solution using new features in Spring 2.0.
Example:
Get a Customer's credit score using a remote credit score service.
- I need a Customer entity, entity = persisted instance, that was previously persisted in theDB. I'll call a DAO's find method to get this entity. The DAO is implemented using hibernate.
// use hibernate to find and re-constitute the customer from the DB
Customer customer = customerDAO.find(33);
- Get the customer's credit score. This will make the remote call to get the score.
int creditScore = customer.getCreditScore().
- The Customer's getCreditScore() method is implemented such that it needs to do a remote call to a CreditAgency to get the creditScore. Customer
DEPENDS on CreditAgency.
public class Customer {
// identifies this customer at the credit agency
long customerNumberAtCreditAgency;
// Collaborator
CreditAgency creditAgency;
// setter for CreditAgency,
this is where the dependency should be injected. public void setCreditAgency(CreditAgency ca){
creditAgency = ca;
}
....
// make a remote call to get this customer's score.
public int getCreditScore(){
//
do the remote call. return creditAgency.getScore(customerNumberAtCreditAgency);
}
}
- the CreditAgency class is an interface that has it's implementation
injected into the Customer
instance using Spring. Another words, the Customer's has a dependency, CreditAgency, that is
injected into it when it's instaniated.
Problem:The DAO is using Hibernate to instaniate, actually re-constitute from the DB, the Customer. I can't have the CreditAgency implementation injected into this Customer instance because Spring isn't creating the object.
Spring won't inject dependencies if it doesn't create the object.
(May be able to use Hibernate Interceptors??)Solution:
Use Spring 2.0 to inject dependencies AFTER the Customer object is created.
- Annotate the customer class.
import org.springframework.beans.factory.aspectj.SpringConfigured;
@SpringConfigured("customer")
public class Customer {
....
}
- Add aspect to the bean config and set the customer bean so
that it doesn't get created by Spring at startup.
<!-- Add the following to the bean config xml.-->
< aop:spring-configured/>
< bean id="customer">
class="Customer"
lazy-init="true"\>
<property name="creditAgency" ref="creditAgency" />
</bean >
Thoughts:I don't really like how the annotation is being put into the customer class. I'd prefer to select which beans are configured in the xml config file.