Question

I have the following class structure

public class Outer{
    private Mapper a;
    ....

    private class MapperA implements Mapper {

    }

    private class MapperB implements Mapper {

    }
}

In my Spring config file I would like to create a an Outer bean, and assign one of MapperA or MapperB as a property. Is this possible?

<bean id="outer" class="mypackage.Outer">
    <property name="a" ?????='????' />
</bean>

Edit: Some more info, based on the feedback from answers:

  1. I got lazy with my above example. I do have a public setter/getter for the Mapper instance variable.

  2. The reason all of the Mapper classes are inner classes is because there could potentially be many of them, and they will only ever be used in this class. I just don't want a ton of cruft classes in my project. Maybe a factory method is a better idea.

Was it helpful?

Solution

Normally you'd need a setter for the Mapper within Outer, and an instance of the required Mapper. But as these are:

  1. private
  2. inner

classes, that becomes a bit tricky (as you've identified). If you make them public, I'm sure you could creae an instance using Outer$MapperA etc. But that seems a little nasty. So:

  1. do they need to be inner and private ?
  2. perhaps Outer can take a String, and determine from that whether to instantiate MapperA or MapperB. i.e. there's some factory capability here.

The simplest thing to do is to really determine if they need to be inner/private. If so, then they really shouldn't be referenced within the config, which should be talking about publicly accessible classes.

OTHER TIPS

Spring can instantiate private inner classes. The actual problem with your config is that they are also non-static, so you need a <constructor-arg .../>:

<bean id="outer" class="mypackage.Outer"> 
    <property name = "a">
        <bean class = "mypackage.Outer.MapperA"> 
            <constructor-arg ref = "outer" />
        </bean>
    </property>
</bean> 

As far as I know, it's impossible until you make MapperA and MapperB usual public classes.

But if you do want to keep them as inner private classes then you can "inject" them manually.

You'll need to create method with @PostInit annotation and initialize your a field there (a = new MapperA () for example, or something more complex). With this approach you should also check that initialization callbacks are switched-on in your spring configuration.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow