How to properly load and configure Spring beans fr

2019-04-09 23:02发布

问题:

Currently I have a utility jar that contains a number of datastore services. Behind the scenes these datastore services use Spring Data MongoDB, and everything is configured using an app-context.xml file in the utility jar. I want this utility jar to be able to change the backing store without having to change anything that uses this utility jar.

Now, I want to create a spring mvc web application that uses the datastore services from this utility jar.

How do I set this up so that the spring mvc web app (or any other jar) can easily use the datastore services without having to know too much about the utility jar, but still have the beans in the utility jar loaded properly?

I was thinking of adding a new java bean class to the utility jar that would load the app-context in it's own jar, and then set some properties on itself for the services. Then the spring mvc would create a bean using this new class in my utility jar, and reference the services through this bean.

/**
* This bean would exist in the utility jar, and other jars/webapps would
* create a new instance of this bean.
*/
public class Services {

    private MyAService myAService;
    private MyBService myBService;

    public Services() {
       ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("app-context.xml");

       // these are configured in the app-context.xml
       this.myAService = ctx.getBean("myAService");
       this.myBService = ctx.getBean("myBService");
    }
}

Is this a good way to go about this? It seems like I would now have two spring application contexts, is that ok? How do I ensure that the proper app-context.xml is loaded, and not one from another jar? Is there a better way of doing this?

回答1:

Since nobody has answered, I just went with my approach and it seems to work, though with a slight modification to allow the bean to destroy the internal context properly.

In your utility jar create a class that loads the app context xml like so:

public class Services implements DisposableBean {

    ClassPathXmlApplicationContext ctx;
    private MyAService myAService;
    private MyBService myBService;

    public Services() {
       this.ctx = new ClassPathXmlApplicationContext("services-context.xml");

       // these are configured in the services-context.xml
       this.myAService = ctx.getBean("myAService");
       this.myBService = ctx.getBean("myBService");
    }

    // Add getters for your services

    @Override
    public void destroy() throws Exception {
       this.myAService = null;
       this.myBService = null;
       this.ctx.destroy();
       this.ctx = null;
    }
}

Make sure your "services-context.xml" file is unique on the classpath. You can do this by putting it in a folder structure that matches the package structure.

In your other jar/war, create the beaning using something like:

<bean id="services" class="Services" destroy-method="destroy"/>

Or, if your other jar/war doesn't use spring, then you do something like:

Services s = new Services();
//... use your services, then clean up when done
s.myAService.doSomething();
s.destroy();


回答2:

Two approaches by which you can solve this : (Please include the dependency as part of pom.xml)

  1. To manually include only the required utility beans into this new application-context.xml with the path referring to those class paths. That's the beauty of spring to create the selective bean only.

  2. Have a properties file (Include this in the new application-context.xml)

<context:property-placeholder location="WEB-INF/utility.properties"/>

<import resource="${application.path.of.utility.jar}"/>

And define path ao the utility jar

application.path.of.utility.jar=/utility/jar/path/application_context.xml