Kovalsky
Kovalsky

Reputation: 349

How to specify which subclass Spring should use

In my spring-based project I have a core module ('core') with a class

@Component
public class Superclass {
    // stuff
}

instances of which are injected by type throughout the code like this:

public class AService {

    @Autowired
    private Superclass superclass;

    // service stuff
}

I also have two other modules that depend on the core module and one of which (let's call it 'module1') extends Superclass:

@component
public class Subclass extends Superclass {
    // overridden stuff
}

The other module ('module2') uses Superclass as is.

Now I want that when I compile and run 'child1' an instance of Subclass is used everywhere an instance of Superclass is expected. So I write a configuration class:

@Configuration
public class Module2Configuration {

    @Bean
    public Superclass superclass(){
        return new Subclass();
    }
}

When I run this I see both Superclass and Subclass instantiated which is definitely not what I want. How do specify in 'module1' which type Spring should instantiate?

Upvotes: 2

Views: 15643

Answers (3)

wilbur_zzz
wilbur_zzz

Reputation: 11

There are 2 methods: Use @Qualifier("SubclassName") Or Mark your subclass as @Component and declare the subclass when @Autowired

In your case:

  1. Use @Qualifier("SubclassName")

    @Component
    public class Superclass {
        // stuff
    }
    
    @component
    public class Subclass extends Superclass {
        // overridden stuff
    }
    
    public class AService {
    
        @Autowired
        @Qualifier("Subclass")
        private Superclass superclass;
    
        // service stuff
    }
    

2.Mark your subclass as @Component and declare the subclass when @Autowired

    public class Superclass {
        // stuff
    }

    @component
    public class Subclass extends Superclass {
        // overridden stuff
    }

    public class AService {

        @Autowired
        private Subclass subclass;

        // service stuff
    }

Upvotes: 1

Jens Birger Hahn
Jens Birger Hahn

Reputation: 917

Spring eagerly instantiates singleton beans as stated in the documentation:

By default, ApplicationContext implementations eagerly create and configure all singleton beans as part of the initialization process.

which might explain why both @Components are created.

To specifiy which implementation is provided as a dependency you might want to check on Qualifiers that enable to choose between different implementations. In combination with lazy loading this should do the trick.

Depending on your personal taste you could also use delegation instead of inheritance using a separated interface:

public interface MyService {
    public String foobar(int baz);
}

public static class CommonBehavior {
    // whatever is used by Superclass and Subclass
}

@Component @Lazy
public class FormerSuperClass implements MyService {
   private final CommonBehavior ...;
   ...
}

@Component @Lazy
public class FormerSubClass implements MyService {
   private final CommonBehavior ...;
   ...
}

Good luck!

Upvotes: 2

michal
michal

Reputation: 1806

You can use @Qualifier("some name") annotation. There is more information about that: http://blogs.sourceallies.com/2011/08/spring-injection-with-resource-and-autowired/

Upvotes: 3

Related Questions