views:

103

answers:

1

We have a legacy system where something like a Service Locator is used to instantiate and provide all service objects:

class ServiceLocator {

    ServiceA serviceA;
    ServiceB serviceB;

    public ServiceLocator () {
        serviceA = ...;
        serviceB = ...;
    }

    public ServiceA getServiceA() {
        return serviceA;
    }

    public ServiceB getServiceB() {
        return serviceB;
    }
}

(imagine 70 more fields and getters...)

This object is then passed around from class to class to provide access to the service objects.

It is outside the scope of the project to change this design for existing code, but to at least not make things worse, we would like to introduce Spring to progressively instantiate future services with DI similar to http://stackoverflow.com/questions/447715/introducing-an-ioc-container-to-legacy-code.

In contrast to the aforementioned situation, we already know how we will access the spring created spring bean objects from our legacy code. Our problem are objects we plan to create with spring, that need any of the service objects created outside of the spring context.

We came up with the following solution:

Create a static accessor for the ServiceLocator and set it in the constructor, load the spring application context object. In the spring configuration create a bean for the ServiceLocator with the static accessor as described in Section 3.3.2.2 in the Spring reference:

<bean id="serviceLocator" 
  class="ServiceLocator"
  factory-method="getInstance"/>

for each Service create another bean using "instance factory method" as described in Section 3.3.2.3:

<bean id="serviceA"
  factory-bean="serviceLocator"
  factory-method="getServiceA"/>

Create other beans referencing these "dummy beans".

I guess this would work, but creates a lot of seamingly unnessessary pseudo configuration. What I'd rather like is something like this:

"If a bean is referenced and that bean is not explicitly defined, search for a method with the needed signature and name in the ServiceLocator class and use this object."

Is it possible to do so? Are there any entry points into the spring bean instantiation process that I am not aware of and that can be used here? Can I do this by subclassing the spring application context class?

Any help would be greatly appreciated!

+1  A: 

You can define a BeanFactoryPostProcessor to populate your application context with beans from ServiceLocator.

In BeanFactoryPostProcessor, use beanFactory.registerSingleton(...) to add a fully instantiated bean, or ((BeanDefinitionRegistry) beanFactory).registerBeanDefinition(...) to add a definition (note that some application contexts may not implement BeanDefinitionRegistry, though all typical contexts implement it).

axtavt
thx axtavt your suggestion looks much better than my initial idea, I'll have a look into it!
delete