Spring bean overriding between projects
Our application is split into two layers. There is the core
layer (a layer that is common between multiple projects) and there is the
customer/customization layer (layer that is customized per customer). What is
needed is to enable the customer layer to override the core dao repository. This
means that if in the core there is a dao:
@Repository
public class UserHibernateDao extends GenericHibernateDao<User>
implements UserDao {
public User getUser(){
return
findUniqueByNamedQuery("User.findUserById",id);
}
}
The customer layer wants to change the getUser method in the
core application layer to:
@Repository
public class UserHibernateDaoEx extends UserHibernateDao<User>
implements UserDao {
@Override
public User getUser(){
return
findUniqueByNamedQuery("User.findUserExById",id);
}
}
The question is how to override the functionality in spring
so that the customer layer bean will be injected into the core classes.
The core classes can use one of the following annotations to
inject to UserDao to its classed:
@Autowire, @Resource, @Inject
A summary of the differences between them is as follows (http://blogs.sourceallies.com/2011/08/spring-injection-with-resource-and-autowired/):
@Autowired and @Inject
1.
Matches by Type
2.
Restricts by Qualifiers
3.
Matches by Name
@Resource
1.
Matches by Name
2.
Matches by Type
3.
Restricts by Qualifiers (ignored if match is found by name)
The problem is as follows. Client code is as follows:
@Resource
Private UserDao useDao;
The spring component uses the @Repository
annotation for the definition. This annotation is used without a name, so the
default name is for the core: userHibernateDao and for the customer: userHibernateDaoEx.
When spring tries to inject into userDao using the @Resource, it does not find
any component by the name of userDao. Spring then searches by type of UserDao,
and finds two implementations and cannot inject the component. By giving the
same name to both components spring will complain that there are two components
with the same id.
The solution is to use an undocumented feature of spring. You
cannot define two components with the same id in the same xml file. But if you can
define two beans with the same id in two different xml files, the second bean
(depends on the order of the files) will be the one that spring uses.
So in the customer layer, instead of using the @Repository
annotation on the inherited dao, it needs to be defined in an xml file.
Summary:
We have found a way for the customer layer to inherit and
override a spring bean that has been defined in the core layer in such a way
that the new bean definied in the customer layer will be used by the core layer
itself and the overridden functionality from the customer layer.
For more information see: http://beradrian.wordpress.com/2011/05/08/overriding-spring-beans/
No comments:
Post a Comment