|
|
How to auto-create non-existing beans during injection?
Hi!
I'm trying to do some quot;dynamicquot; injection using Spring. What the heck I mean by dynamic? I have a base abstract Dao class that has a generic type (which means the Model) nad has all basic (and even some advanced) persistence operations. Something like this:Code:
public abstract class Daolt;M extends PersistentModelgt; { // a bunch of methods: insert, update, findAll, findByExample, etc
}
The problem is, for simple CRUD operations I have to create quot;emptyquot; Daos like this:Code:
@Repository
public class ProductDao extends Daolt roductgt; { // no methods needed
}
So, I want to achieve the following: if a Dao is not present for some model, create an anonymous implementation automatically and make it available for injection.
Suppose this service class and that the ProductDao above does not exist:Code:
@Service
public class ProductService {
@Autowired private Daolt roductgt; dao; // the bean is not found, create a new repository implementation and inject
}
Did you guys get it? Can someone point me in the right direction? I'm looking at BeanFactory, FactoryBean, PostProcessor but no success until now.
Thanks in advance!
While there are things you could do with FactoryBeans and reflection, in the interest of keeping it simple, I'd suggest a slightly different approach.
Add a constructor to your DAO class that takes the class of the type, i.e.Code:
public class Daolt;M extends PersistentModelgt; { Classlt;Mgt; modelClass;
public Dao(Classlt;Mgt; modelClass) { this.modelClass = modelClass; }
// a bunch of methods: insert, update, findAll, findByExample, etc
}
Now you can just define and inject your DAOs normally, without the need for subclasses. Only downside is you'll need to use XML or Java-based configuration to define the DAOs themselves.
Hope this helps
- Don
Hey Don, thank you very much for your reply.
However I'm looking for something automatic. It doesn't need to be simple because the functionality I've described will be encapsulated on a framework. The simplicity is in the fact that you don't need to create a Dao class (or a Dao definition on the XML) if you need no more than the persistence operations already defined on the abstract Dao.
I'm trying to reach something simple and dynamic, like RoR, Grails and similar, but for Java. The statement is: you don't need to define beans/classes if the functionality you want is already present on a base class.
I'm trying to do something similar (external, on-demand bean construction, based on type for autowiring).
The closest I've come is InstantiationStrategy, which I've implemented but I haven't figured out how to wire it in. My current (broken) code:
Code:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
context.refresh();
AbstractAutowireCapableBeanFactory factory = (AbstractAutowireCapableBeanFactory)context.getBeanFactory();
factory.setInstantiationStrategy(new CustomInstantiationStrategy());
context.setConfigLocation(...);
context.refresh();The closest I've come is InstantiationStrategy, which I've implemented but I haven't figured out how to wire it in. My current (broken) code:
ClassPathXmlApplicationContext is a RefreshableApplicationContext implementation: it'll create a new BeanFactory each time you call refresh(). In order to register your InstantiationStrategy on the right BeanFactory, you need to add a BeanFactoryPostProcessor to the context.
hth,
Alessio
I've came up with a working solution. But is not generic for any bean that does not exists yet, you gotta be careful about to generic solutions like that because they might cause some unexpected behavior.
What I did was the following:
- Since I want to create Dao classes for entities that are mapped but doesn't has a corresponding Dao, I've implemented a org..beans.factory.support.BeanDefi nitionRegistryPostProcessor that: 1. Checks for all beans of type Dao are already registered and the corresponding entity type. 2. For each registered SessionFactory I iterate thru all the mapped entities and those who haven't a corresponding Dao, I register a new bean definition.
Now I can autowire them! (by name since Spring does not work well with generic types, for Spring they are beans of the same type, even if the generic defined types are different)
The code bellow works even if I haven't created a Dao class for the specific entity:
Code:
@Autowired
private Daolt roductgt; productDao; // note that the quot;entityname + Daoquot; is a convention defined on the PostProcessor for the @Autowired to work.
If you're interested in the solution, check the source at
brushingbits/jnap...Processor.java |
|