Here is what i have right now which works fine. All it does is a market class which returns an array of items objects:
I have class market
class market {
public ArrayList<Items> createItems(HashMap<String,String> map) {
ArrayList<Items> array = new ArrayList<Items>();
for (Map.Entry<String, String> m : map.entrySet()) {
Item item = new Item();
item.setName(m.key());
item.setValue(m.value());
array.add(item);
}
return array;
}
}
class Item is simple class with getter and setter for name and value
Here is how my config file looks:
@Configuration
public class MarketConfig {
@Bean
public Market market() {
return new Market();
}
}
How I want to change my code:( REASON: i dont want
Item item = new Item();
in then method. I want Spring to inject it into Market)
class market {
public Item item;
//getters and setters for item
public ArrayList<Items> createItems(HashMap<String,String> map) {
ArrayList<Items> array = new ArrayList<Items>();
for (Map.Entry<String, String> m : map.entrySet()) {
item.setName(m.key());
item.setValue(m.value());
array.add(item);
}
return array;
}
}
@Configuration
public class MarketConfig {
@Bean
@Scope("prototype")
public Item item() {
return new Item();
}
@Bean
public Market market() {
Market bean = new Market();
bean.setItem(item());
}
}
I know that prototype scope will give me new bean each time i call item(); Now i want new bean for each iteration in the for loop of createItems method. How can i tell spring to give me.
One way i know is Do
applicationContext context = new AnnotationConfigApplicationContext();
context.getBean(Item.class);
But is there any other way to get my work done. Thanks
You cannot dependency-inject a prototype-scoped bean into your singleton bean, because that injection occurs only once, when the Spring container is instantiating the singleton bean and resolving and injecting its dependencies.
When you work with a prototype bean in a singleton, you have three options to get a new instance of the prototype: Spring can autowire a single prototype instance when it creates the singleton. It's the default framework behavior. Spring can create a new prototype instance on every call to any method of this prototype.
As a rule of thumb, you should use the prototype scope for all beans that are stateful, while the singleton scope should be used for stateless beans.
Yes, you can create prototype method on demand using look-up method
public abstract class ItemFactory {
public abstract Item createItem();
}
now in applicationContext.xml just put the following:
<bean id="item" class="x.y.z.Item" scope="prototype" lazy-init="true"/>
and configure factory:
<bean id="itemFactory" class="x.y.z.ItemFactory">
<lookup-method name="createItem" bean="item"/>
</bean>
Now all that you need to do in order to use it is Autowire it inside any bean:
and call yout look-up method:
@Service
public class MyService{
@Autowired
ItemFactory itemFactory;
public someMethod(){
Item item = itemFactrory.createItem();
}
}
each time you call createItem()
you will receive the reference to newly created instance of Item class.
P.S: I see that you are using @Configuration
instead of xml you need check if look-up method can be configured inside configuration bean.
Hope it helps.
Update: The trick is simple:
@Configuration
public class BeanConfig {
@Bean
@Scope(value="prototype")
public Item item(){
return new Item();
}
@Bean
public ItemManager itemManager(){
return new ItemManager() {
@Override
public Item createItem() {
return item();
}
};
}
}
It can be simplified if you are using Java 8
@Configuration
public class Config {
@Bean
@Scope(value = "prototype")
public Item item() {
return new Item();
}
@Bean
public Supplier<Item> itemSupplier() {
return this::item;
}
}
And after that you can use this supplier in your Market class to create prototype Item beans.
@Component
public class Market {
private final Supplier<Item> itemSupplier;
@Autowired
public Market(Supplier<Item> itemSupplier) {
this.itemSupplier = itemSupplier;
}
private Item createItem() {
return itemSupplier.get();
}
}
Quite simple and there is no need in additional factory beans or interfaces.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With