8

We were using 4.2.x version of spring and we are using ContextSingletonBeanFactoryLocator to load bean like below

BeanFactoryLocator bfLocator = ContextSingletonBeanFactoryLocator.getInstance("classpath:customBeanRefFactory.xml");
BeanFactoryReference ref = bfLocator.useBeanFactory("sharedApplicationContext");
BeanFactory beanFactory = ref.getFactory();
((AbstractApplicationContext) beanFactory).getBeanFactory().setBeanClassLoader(CustomSpringBeanFactory.class.getClassLoader());
return (ApplicationContext) beanFactory

We are planning to upgrade to spring 5.0.x and figured out ContextSingletonBeanFactoryLocator and classes like BeanFactoryLocator and BeanFactoryReference are removed from spring 5.0 release.

So what are the suggested alternatives to get application context?

@Configuration
@ImportResource("classpath:ourxml")
public class OurApplicationConfiguration {

}


public class OurAppicationFactoryProvider {

    ApplicationContext context;

    public ApplicationContext getApplicationContext() {
        if (context == null) {
            synchronized (this) {
                if (context == null) {
                    context = new AnnotationConfigApplicationContext(OurApplicationConfiguration.class);
                }
            }
        }
        return context;
    }
}

Is this even right approach or there are other alternatives?

Dheeraj Joshi
  • 3,057
  • 8
  • 38
  • 55
  • 1
    Basically the fact that you are getting the `ApplicationContext` is already a flaw, in an application you shouldn't need it (assuming that Spring is creating the context). Your "solution" makes it even worse as that will load the context twice (assuming Spring is also instantiating the context). – M. Deinum Jan 25 '18 at 06:27
  • We have few legacy bean which are not annotated by spring annotation. So we were using application context to get them – Dheeraj Joshi Jan 25 '18 at 06:57
  • Legacy beans not annotated but get them through the context? If you can get them through the context you can inject them... If your only task is that you can just `@Autowire` the `ApplicationContext` into your `OurAppicationFactoryProvider`. Don't create a new one (in the worst case you also have class loader issues and you load the application numerous times). – M. Deinum Jan 25 '18 at 06:59
  • I will try that. – Dheeraj Joshi Jan 25 '18 at 07:32

2 Answers2

6

In my legacy application which was based on BeanFactoryLocator/beanRefContext.xml mechanism mentioned at https://jira.spring.io/browse/SPR-15154, I added a Singleton class to create application context and use that context. My code is

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public enum SpringContextUtil {
    INSTANCE;
    ApplicationContext context;

    public ApplicationContext getApplicationContext() {
        if (context == null)
            context = new ClassPathXmlApplicationContext("classpath*:beanRefContext.xml");
        return context;
    }

}

and I replaced

    final BeanFactoryReference ref = ContextSingletonBeanFactoryLocator.getInstance().useBeanFactory(contextKey);
    AbstractApplicationContext context = ((AbstractApplicationContext) ref.getFactory());

by

AbstractApplicationContext context = (AbstractApplicationContext)SpringContextUtil.INSTANCE.getApplicationContext().getBean(contextKey);

Hopefull that would help someone in my shoes.

The solution might not be applicable to all situation.

Ashish
  • 14,295
  • 21
  • 82
  • 127
0

In a similar situation we reintroduced the locator mechanism directly into our code.

  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Nov 24 '21 at 11:51