ServiceLocatorFactoryBean in Spring framework as the name suggests is an implementation of service locator design pattern and helps with locating the service at run time.
ServiceLocatorFactoryBean helps if you have more than one implementation of the same type and want to use the appropriate implementation at the run time i.e. you have an interface and more than one class implementing that interface and you want to have a factory that will return an appropriate object at run time.
How ServiceLocatorFactoryBean works
ServiceLocatorFactoryBean class in Spring has a field serviceLocatorInterface that takes an interface which must have one or more methods with the signatures MyService getService() or MyService getService(String id)). Spring framework creates a dynamic proxy which implements that interface, delegating to an underlying BeanFactory.
When you call getService(String id)) method of your interface passing the bean id as an argument, internally through the proxy BeanFactory.getBean(String id) is called, returning the bean whose name is passed as an argument to the getBean() method of the BeanFactory.
Advantage of having a ServiceLocatorFactoryBean is that such service locators permit the decoupling of calling code from the BeanFactory API, by using an appropriate custom locator interface. They will typically be used for prototype beans, i.e. for factory methods that are supposed to return a new instance for each call.
Spring ServiceLocatorFactoryBean Example
Let’s see an example to make things clearer as the theory looks quite complex!
We want to determine at the run time whether to make a cash payment or card payment based on the input (argument passed). So we have an interface IPayment and implementing classes CashPayment and CardPayment.
public interface IPayment{ void executePayment(); } public class CashPayment implements IPayment{ public void executePayment() { System.out.println("Perform Cash Payment "); } } public class CardPayment implements IPayment{ public void executePayment() { System.out.println("Perform Card Payment "); } }
Service locator interface
This service locator interface will be injected in ServiceLocatorFactoryBean.public interface PaymentFactory { public IPayment getPayment(String paymentType); }
Here is the bean where ServiceLocatorFactoryBean will be injected, it also has a method where the injected factory bean instance is used to get the required bean by bean name.
import org.springframework.beans.factory.annotation.Autowired; public class PaymentService { @Autowired private PaymentFactory paymentFactory; public void setPaymentFactory(PaymentFactory paymentFactory) { this.paymentFactory = paymentFactory; } public void makePayment(String paymentType){ IPayment payment = paymentFactory.getPayment(paymentType); payment.executePayment(); } }
XML Configuration
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/> <!-- Prototype bean since we have state --> <bean id="cashPayment" class="org.netjs.exp.Spring_Example.CashPayment" scope="prototype" /> <bean id="cardPayment" class="org.netjs.exp.Spring_Example.CardPayment" scope="prototype" /> <!-- ServiceLocatorFactoryBean --> <bean id="paymentFactory" class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean"> <property name="serviceLocatorInterface" value="org.netjs.exp.Spring_Example.PaymentFactory"/> </bean> <bean id="payServiceBean" class="org.netjs.exp.Spring_Example.PaymentService"> </bean> </beans>You can run the example using the following code.
import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App { public static void main( String[] args ){ AbstractApplicationContext context = new ClassPathXmlApplicationContext ("appcontext.xml"); PaymentService payService = (PaymentService)context.getBean("payServiceBean"); payService.makePayment("cardPayment"); context.registerShutdownHook(); } }
Note that "cardPayment" is passed here as the payment type. From the service factory dynamic proxy implementation Spring framework will internally call BeanFactory.getBean(“cardPayment”) to return an instance of the specified bean.
That's all for this topic ServiceLocatorFactoryBean in Spring. If you have any doubt or any suggestions to make please drop a comment. Thanks!
>>>Return to Spring Tutorial Page
Related Topics
You may also like-
No comments:
Post a Comment