How many ways are there to Config and Bootstrap a Standalone Spring Application?

Quite a few, it seems..

Let's start with a very simple XML Configuration File:

Study the classes below, please
public interface Foo {
    void foo();
}
 
public class FooImpl implements Foo {
    public void foo() {
        System.out.println("Foo, foo, foo!!!");
    }
}
 
public interface Bar {
    void bar();
}
 
import org.springframework.beans.factory.annotation.Required;
 
public class BarImpl implements Bar {
 
    Foo foo;
 
    public void bar() {
        foo.foo();
        System.out.println("Bar, bar, bar!!!");
    }
 
    @Required
    public void setFoo(Foo foo) {
        this.foo = foo;
    }
}

Now the beans.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd">
 
    <bean id="foo" class="biz.tugay.FooImpl"/>
    <bean id="bar" class="biz.tugay.BarImpl">
        <property name="foo" ref="foo"/>
    </bean>
 
</beans>

And the Test Class:
package biz.tugay;
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
public class App {
 
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Bar barImpl = context.getBean(Bar.class);
        barImpl.bar();
    }
}

All fine!!! Now let's introduce Annotations:

beans.xml changed slightly:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd 
                           http://www.springframework.org/schema/context 
                           http://www.springframework.org/schema/context/spring-context.xsd">
 
    <context:annotation-config/>
 
    <bean id="foo" class="biz.tugay.FooImpl"/>
    <bean id="bar" class="biz.tugay.BarImpl"/>
 
</beans>

And in BarImpl.java we now have:
import org.springframework.beans.factory.annotation.Autowired;
 
public class BarImpl implements Bar {
 
    Foo foo;
 
    public void bar() {
        foo.foo();
        System.out.println("Bar, bar, bar!!!");
    }
 
    @Autowired
    public void setFoo(Foo foo) {
        this.foo = foo;
    }
}

This is cool as well.. Now, let's introduce Component Scan:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd">
 
    <context:annotation-config/>
    <context:component-scan base-package="biz.tugay" />
</beans>

And the classes will need the @Component annotation..
@Component
public class FooImpl implements Foo {
    public void foo() {
        System.out.println("Foo, foo, foo!!!");
    }
}
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
@Component
public class BarImpl implements Bar {
 
    Foo foo;
 
    public void bar() {
        foo.foo();
        System.out.println("Bar, bar, bar!!!");
    }
 
    @Autowired
    public void setFoo(Foo foo) {
        this.foo = foo;
    }
}

You think this is all? No no no... Let's get rid of the beans.xml file and introduce a Java Class that we can use for Configuration:
package biz.tugay;
/* User: koray@tugay.biz Date: 03/12/15 Time: 22:40 */
 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
@Configuration
public class MyConfigClass {
 
    @Bean
    public Foo foo() {
        return new FooImpl();
    }
 
    @Bean
    public Bar bar() {
        BarImpl bar = new BarImpl();
        bar.setFoo(foo());
        return bar;
    }
}

In the mean time, let me show you what the Interfaces and Classes we have look like:
public interface Foo {
    void foo();
}
 
public class FooImpl implements Foo {
    public void foo() {
        System.out.println("Foo, foo, foo!!!");
    }
}
 
public interface Bar {
    void bar();
}
 
import org.springframework.beans.factory.annotation.Required;
 
public class BarImpl implements Bar {
 
    Foo foo;
 
    public void bar() {
        foo.foo();
        System.out.println("Bar, bar, bar!!!");
    }
 
    @Required
    public void setFoo(Foo foo) {
        this.foo = foo;
    }
}

And of course, our Test Class will change slightly as well:
public class App {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfigClass.class);
        Bar barImpl = context.getBean(Bar.class);
        barImpl.bar();
    }
}

Now, as in XML, let's introduce Annotations!!!

Our Config class changed a little:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
@Configuration
public class MyConfigClass {
 
    @Bean
    public Foo foo() {
        return new FooImpl();
    }
 
    @Bean
    public Bar bar() {
        return new BarImpl();
    }
}

and BarImpl has changed slightly as well:
import org.springframework.beans.factory.annotation.Autowired;
 
public class BarImpl implements Bar {
 
    Foo foo;
 
    public void bar() {
        foo.foo();
        System.out.println("Bar, bar, bar!!!");
    }
 
    @Autowired
    public void setFoo(Foo foo) {
        this.foo = foo;
    }
}

Now let's use ComponentScan:
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
 
@Configuration
@ComponentScan(basePackages = "biz.tugay")
public class MyConfigClass {
 
}

and we need to tell Spring the classes that are Components:
@Component
public class FooImpl implements Foo {
    public void foo() {
        System.out.println("Foo, foo, foo!!!");
    }
}
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
@Component
public class BarImpl implements Bar {
 
    Foo foo;
 
    public void bar() {
        foo.foo();
        System.out.println("Bar, bar, bar!!!");
    }
 
    @Autowired
    public void setFoo(Foo foo) {
        this.foo = foo;
    }
}

Man, that is a lot of options we have!!! Where there is choice, there is misery!