Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
405 views
in Technique[技术] by (71.8m points)

java - Singleton Bean instance by generic parameter

I would like to have a singleton bean instance by generic parameter based on a single @Component generic class.

(I am using Spring 4.)

My code :

I have an interface like this :

public interface Mapper<I, O> {
    ...
}

And multiple implementation of it which are Spring @Components (singletons). Something like this :

@Component
public class MapperA implements Mapper<ClazzAI, ClazzAO> {
    ...
}

and

@Component
public class MapperB implements Mapper<ClazzBI, ClazzBO> {
    ...
}

where ClazzAI, ClazzAO, ClazzBI and ClazzBO are basic Java classes.

I have another Spring @Component (singleton) which have a Mapper class as a generic parameter :

@Component
public class TransformerImpl<I, O, M extends Mapper<I, O>> {

    /** The Mapper */
    protected final M mapper;

    @Inject
    private TransformerImpl(final M mapper) {

        this.mapper= mapper;
    }

    ...
}

and I would like to use it like this :

@Inject
private TransformerImpl<ClazzAI, ClazzAO, MapperA> transformerA;

@Inject
private TransformerImpl<ClazzBI, ClazzBO, MapperB> transformerB;

The problem :

But Spring is not able to instantiate those 2 objects because it founds 2 implementations of Mapper : MapperA and MapperB even if I specify which implementation I want as a generic parameter.

Any idea how to make it without the need of instantiate all of those beans in a @Configuration class ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You're asking for a singleton but requiring two injection points

@Inject
private TransformerImpl<ClazzAI, ClazzAO, MapperA> transformerA;

@Inject
private TransformerImpl<ClazzBI, ClazzBO, MapperB> transformerB;

for differently constructed objects. That doesn't make much sense.

You now realize you need two beans. If you can't (don't want to) do it in a @Configuration class with @Bean factory methods, you'll need to declare (and scan) two separate @Component classes. (I made your parent constructor public here.)

@Component
class MapperATransformerImpl extends TransformerImpl<ClazzAI, ClazzAO, MapperA> {
    @Inject
    public MapperATransformerImpl(MapperA mapper) {
        super(mapper);
    }
}

@Component
class MapperBTransformerImpl extends TransformerImpl<ClazzBI, ClazzBO, MapperB> {
    @Inject
    public MapperBTransformerImpl(MapperB mapper) {
        super(mapper);
    }
}

When processing the injection target

@Inject
private TransformerImpl<ClazzAI, ClazzAO, MapperA> transformerA;

Spring will find the MapperATransformerImpl, which is of type TransformerImpl<ClazzAI, ClazzAO, MapperA> and inject that.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...