≡ Menu
Spring Tutorial – JavaConfig

Spring Tutorial – JavaConfig

Spring Tutorial – Starting with Spring JavaConfig

Remember Sharing is caring! So if you get something from this Spring tutorial please share it with others on facebookgoogle+, LinkedIn, Twitter  etc… so it may help them too! :)

There’s an area of the Spring Framework that has gained a lot of traction in the past couple of years, its called Spring JavaConfig 

So, what is Spring JavaConfig ?

Spring JavaConfig can be thought of as an XML configuration equivalent, only written in Java code!

This may sound odd to begin with because as we often talk about and try to externalize or decoupling ‘stuff’ away from our Java applications, usually into files of various formats; i.e. XML or properties files… but now we’re talking about taking ‘stuff’ out of files and putting it back into our Java Code! Why?

There’re a couple very good reasons really, when we stop and think about. It really depends upon what ‘stuff’ is being move back into your Java code.

Spring JavaConfig provides us with a great way to configure our Spring enabled Java applications without getting tangled up in “XML hell”, while at the same time keeping the “decoupling” advantages of XML (i.e. separate the configuration “stuff” from the actual application code) and gain the advantage of Java compile time checks!

Have you ever been in that position where you’ve built a large spring enabled Java application successfully to find you made a silly typo in the configuration. Only to show itself when the code is sent off for testing or worse a demo… ouch!! Spring JavaConfig would nail these types of problems by failing fast at compile time, nice! Also, personally I prefer to read Java code any day of the week, rather cryptic XML namespaces.

So how does it work ?

In this Spring Tutorial I want to start looking at how we go about wiring a very basic application using Spring JavaConfig. We will look at what classes will contain our configuration code, how to load our new configuration class and take a look at how can we can inject beans into other beans using this approach.

Let’s start by looking at what replaces the trusted XML configuration file. Well there’re no surprises that it’s a Java class. Yes, just like any other POJO but with the added annotation of;

@Configuration

So the most basic configuration class would look like;

@Configuration

public class AppConfig {

}

(I would recommend suffixing the class name with ‘Config’, just to help readability in the code base but that’s only preference.)

The basic class above is the same as having an XML file called AppConfig.xml. It follows then that we can put our bean definitions into this class! Let’s try an example;

@Configuration

public class AppConfig {

 

       @Bean

       public Bar bar() {

                return new Bar();

        }

 

}

We now have our first bean definition within our first Spring JavaConfig configuration class.

The method bar() returns an instance of the Bar class.

Note, the annotation of @Bean. This tells Spring that the method is a bean definition. When JavaConfig sees this annotation it will execute the method and register the return value as a bean in a BeanFactory.

Also, remember the ‘id’ or ‘name’ attribute in the <bean> XML element, well the method name replaces that and acts as the bean ‘id’.

So, how do we wire beans with dependencies with other beans ?

It’s as simple as having a method calling another method! Yes it’s that straight forward!

Let’s expand our example;

@Configuration

public class AppConfig {

         @Bean

         public Foo foo() {

                   return new Foo();

          }

         @Bean

        public Bar bar() {

                   return new Bar();

         }

}

We now have 2 method annotated with the @Bean

bar() returns an instance of Class Bar

foo() returns an instance of class Foo

This gives us two bean definitions now; for class Bar and class Foo.

However, if we have a dependency between the two, how can we wire the two instances together manually. (note: NOT using autorwiring.)

In XML, we would have used either constructor or setter injection, well we can use the same principle in Spring JavaConfig.

If  Foo has a dependency of Bar, we can inject Bar using  constructor injection, by just calling the bar() method;

(Remember you will need to implement the constructor in the Foo class and have an instance variable to contain it, just as you would if you used XML for the configuration.)

  return new Foo(bar());

Now the two beans will be wired together.

It’s worth noting that because our methods are annotated with @Bean, some spring magic goes on behind the scenes.

As an example, we modify our code so we have two methods which construct Foo instances, both injecting bar()

i.e;

@Configuration

public class AppConfig {

    @Bean

    public Foo foo() {

          return new Foo(bar());

      }

    @Bean

    public Foo foo2() {

          return new Foo(bar());

    }

    @Bean

    public Bar bar() {

         return new Bar();

    }

}

How many Bar instances would we have ?

As with XML configuration, the Spring JavaConfig default scope is singleton, so we would have just the one instance of Bar in the Spring container, even though “return new Bar()” is called twice!

This magic occurs because the class AppConfig is annotated with @Configuration, telling spring to proxy the class, so it can manage the beans created inside it. Now because of this the AppConfig class cannot be made ‘final’ and doing so would result in an exception being raised. Another side effect is that the class will always require a no argument constructor, in other words if you create a constructor with an argument, you will also need to create a constructor with no arguments, previously Java created it for you automagically.

We can alter this default behaviour by simply changing the ‘scope’ of the method  bar() with the @Scope annotation (org.springframework.context.annotation.Scope) and provide it with the “prototype” string.

Now each call of method bar() will result in a new instance of Bar being created.

@Bean

   @Scope(“prototype”)

    public Bar bar() {

           return new Bar();

    }

From the previous example of foo() and foo2() we would now have two instances of Bar being created!

To wrap up this first tutorial on Spring JavaConfig, how do we load the configuration of our new configuration class ?

 

When working with XML configuration we rely on the ClassPathXmlApplicationContext, org.springframework.context.support.ClassPathXmlApplicationContext

now with Springh JavaConfig we use a different class; AnnotationConfigApplicationContext, org.springframework.context.annotation.AnnotationConfigApplicationContext

in our simple Java client class, which is currently dependent on XML.

final ClassPathXmlApplicationContext context = new          ClassPathXmlApplicationContext(“/spring/AppConfig.xml”))

That changes now to;

final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class)

Notice the configuration class ‘AppConfig.class’ is passed in via constructor here.

Other code in our application stays the same, thanks to the beauty of Springs encapsulation.

If you would like to see more articles on Spring JavaConfig, please leave a comment or share this article!

Remember Sharing is Caring !!

Also check out my online video courses Spring Tutorial course Part: 2 it has great tutorials on Spring JavaConfig, including downloadable source code.

thanks for reading & happy Coding !!
Bruce

 

in Blog from the Den, Spring Tutorials

About the author: Bruce is a techie, a gadget geek, programmer, mentor and all round technology nut. He holds two degrees in computer science, with over 25 years in the software business. Currently working freelance as a software engineer and programming mentor. He loves what technology can do for us. Building applications using functional, Object Orientated languages & polyglot persistence helps him reconnect with the feeling of building something tangible. To learn more about Bruce, follow him on Twitter @denofprogram

{ 0 comments… add one }

Leave a Comment