Search code examples
javaspringguicespring-ioc

Having Spring's IoC container instantiate beans with zero config (like Google Guice's behaviour)


I have a hobby-project which I would like to migrate to Spring.

As an example I have the following classes:

public class OtherBean {
    public void printMessage() {
        System.out.println("Message from OtherBean");
    }
}


public class InjectInMe {
    @Inject OtherBean otherBean;

    public void callMethodInOtherBean() {
        otherBean.printMessage();
    }
}

However as I read the documentation, I must annotate all classes to be managed by Spring with an annotation like @Component (or others that are similar).

Running it with the following code:

public class SpringTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.refresh();

        InjectInMe bean = context.getBean(InjectInMe.class);
        bean.callMethodInOtherBean();
    }
}

Gives me the error:

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [somepackage.InjectInMe] is defined
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:371)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:331)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:968)
    at somepackage.SpringTest.main(SpringTest.java:10)

My question is: is there a way to make Spring manage any class I ask the ApplicationContext to instantiate without me having to register them in an Annotated Config (or XML config)?

In Guice I can just inject into the class

public class GuiceTest {
    static public class GuiceConfig extends AbstractModule {

        @Override
        protected void configure() {}

    }
    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new GuiceConfig());
        InjectInMe bean = injector.getInstance(InjectInMe.class);
        bean.callMethodInOtherBean();
    }
}

Gives me the output:

Message from OtherBean

Is there anyway I can make Spring work like Guice? As in make Spring inject my beans without me having to register or scan packages for classes annotated with @Component-like annotations?

Any Spring gurus have a way to solve this problem?


Solution

  • My question is: is there a way to make Spring manage any class I ask the ApplicationContext to instantiate without me having to register them in an Annotated Config (or XML config)?

    No, it's not possible. This is simply not how Spring is designed. You must either implicitly (e.g. scan + annotation) or explicitly (e.g. XML bean definition) register your beans.

    The least you can do is something like:

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.register(OtherBean.class);
    context.register(InjectInMe.class);
    context.refresh();