This is useful when a Singleton bean need to use a
non-singleton bean. Sometime your application may need to collaborate a
prototype bean with a singleton bean to satisfy your business logic. That is
your singleton bean is dependent on a prototype bean. Let’s consider three
beans
- Customer
- Sales Person
- Product
A customer may ask a sales Person to show different type of
products from the repository. Let’s assume you have gone to a garment shop to
buy a new shirt for the lucky date with your new girlfriend. So, it’s a
tough choice and you may like to try different colors and styles and finally
you will choose one.
So, if we describe the above situation in the form of
business logic inside one of your module, it will look like this,
The
sales Person should show a new product every time he
requests. Let’s assume Customer and Sales Person to be singleton bean in
your
Spring container and Product as prototype. But based on bean life-cycle a
prototype bean can not be injected to a singleton bean. In this case
Customer
and Sales Person is singleton, hence Sales Person cannot request a new
Product, it's being a prototype. But Spring has a solution and that is
Method
Injection.
The Customer Class:
public class Customer
{
@Autowired
private SalesPerson salesPerson;
public Customer() {
System.out.println("Customer arrived");
}
public void
askProduct() {
System.out.println("Ask for product");
salesPerson.bringProduct();
}
}
The Product Class:
public class Product {
private int i = 0;
public Product() {
System.out.println("product loaded");
}
public void
showProduct() {
System.out.println("Get product ID " + i++);
}
}
The SalesPerson Class:
public abstract class SalesPerson {
protected abstract Product
getFromRepository();
public SalesPerson() {
System.out.println("Sales person called");
}
public void
bringProduct() {
getFromRepository().showProduct();
}
}
The Main Class:
public class
BuyShirtForMyDate {
public static void main(String[] args) {
ApplicationContext
context = new ClassPathXmlApplicationContext("META-INF/spring-context.xml");
Customer
customer = (Customer) context.getBean("customer");
customer.askProduct();
customer.askProduct();
}
}
The Spring context:
<bean id="customer"
class="Customer" />
<bean id="product" class="Product"
scope="prototype"/>
<bean id="salesPerson"
class="SalesPerson">
<lookup-method bean="product"
name="getFromRepository"/>
</bean>
Output
Customer arrived
Sales person called
Ask for product
New product loaded
Get product ID 0
Ask for product
New product loaded
Get
product ID 0
From the above example you can see that, SalesPerson is an
abstract class, generally spring can not create a bean of the abstract class,
in this case spring will subclass your SalesPerson class dynamically and
override the lookup-method,
that is getFromRepository.
The method that is to be
'injected' must have a signature of the following form:
<public|protected> [abstract]
<return-type> theMethodName(no-arguments);
Also you can see that product is a prototype bean. Whenever
a bean request comes Spring will execute getFromRepository method in
SalesPerson class and will return a new Product bean. Hope this discussion
makes some sense.
Comments
Post a Comment