Home > OS >  How does Autowire work when referring only to a base class
How does Autowire work when referring only to a base class

Time:11-07

I am trying to extend existing code which auto-wires a number of components which share the same base class and are only referred to by their base class, ei:

@Configuration
public class NavigationHotKeyBindConfigs {
    private static final Logger logger = LogManager.getLogger(NavigationHotKeyBindConfigs.class);

    @Autowired
    private HotKeyConfig hotKeyConfig;

    @Autowired
    private ANavigation upNavigation;

    @Autowired
    private ANavigation downNavigation;

    @Autowired
    private ANavigation centerOnSelection;

    @Autowired
    private ANavigation handVerify;

public abstract class ANavigation {
    @Autowired
    protected ScrollSchedulerConfigurer scrollSchedulerConfigurer;

    public abstract void execute(DetectionView DetectionView);
}

@Component
public class DownNavigation extends ANavigation{

    private static final Logger logger = LogManager.getLogger(DownNavigation.class);

    public void execute(DetectionView detectionView){
        logger.info(String.format("Received: Navigation key %s", ENavigationKey.DOWN.name()));
        scrollSchedulerConfigurer.stop();
        detectionView.selectNextDetection();
    }
}


@Component
public class UpNavigation extends ANavigation{

    private static final Logger logger = LogManager.getLogger(UpNavigation.class);

    public void execute(DetectionView detectionView){
        logger.info(String.format("Received: Navigation key %s", ENavigationKey.Up.name()));
        scrollSchedulerConfigurer.stop();
        detectionView.selectPrevDetection();
    }
}

I don't understand how spring is ever supposed to match up upNavigation/downNavigation with the UpNavigation/DownNavigation components respectively. Was this just bad design from the original author or is there a subtlety I'm missing?

This lack of understanding is also causing some issues as the centerOnSelection and handVerify objects end up NULL after autowiring though they follow the same pattern in every way I can see. Interestingly, this last behavior is different when run in the intellij IDE vs when run out of a .jar

CodePudding user response:

@Autowired first looks at the type of the variable and then the name of the variable to match the correct bean. By default, the name of a class marked with @Component is its short name, e.g. upNavigation for the UpNavigation class.

@Autowired
private ANavigation upNavigation;

is the same as

@Autowired
@Qualifier("upNavigation")
private ANavigation upNavigation;

And

@Component
public class UpNavigation

is the same as

@Component("upNavigation")
public class UpNavigation

Since the names match, Spring is able to find the corresponding bean.

CodePudding user response:

You can do it like this ...

Let's say we have two beans which have the same base class or interface

@Component("fooFormatter")
public class FooFormatter implements Formatter {
 
    public String format() {
        return "foo";
    }
}

@Component("barFormatter")
public class BarFormatter implements Formatter {
 
    public String format() {
        return "bar";
    }
}

Then we inject them like this ...

public class FooService {
     
    @Autowired
    @Qualifier("fooFormatter")
    private Formatter formatter;
}

From the point of view of clarity and maintainability this seems to be the best solution

  • Related