Spring Autowiring & Component Scanning Problems - Part 4: Application Contexts

Part 3 can be found here

Spring loads beans into application contexts. Any beans declared in XML files or any annotated classes found via component scanning are placed into a suitable application context - either the root application context or one specific to the web application that the bean is declared in.

Any beans declared (or scanned for) which are not DispatcherServlet related (i.e. not -servlet.xml files) are placed into one big root application context bucket, the support for separate XML application context files is purely a convenience for you to manage the logical separation of the beans.

Each DispatcherServlet gets it's own WebApplicationContext which inherits all the beans from the root application context, overlaying all the beans defined within it's web application scope (i.e. any beans within -servlet.xml). Once all the DispatcherServlet's beans are loaded it will attempt to autowire them together and this is where the potential problems start.

Part 5 can be found here

Spring Autowiring & Component Scanning Problems - Part 3: Autowiring

Part 2 can be found here

Having a load of beans instantiated in an application context is one thing, having them wired together so that they know about each other is another. Wiring can be done either using XML or via the @Autowired annotation. The annotations on their own don't cause Spring to wire the beans, you need to turn on annotation support for Spring to find them:

<context:annotation-config/>
When added to an application context XML file it instructs Spring to look through all the loaded beans in the relevant application context for annotations like @Autowired, @Qualifier & @Required. In a reasonably mature Spring application you could have the beans being wired together in a number of ways:
  • Explicit <property> XML elements referencing other beans
  • The addition of autowire="byType" or autowire="byName" XML attributes
  • @Autowired annotations inside normal classes declared as beans in XML
  • @Autowired annotations inside @Component-based classes
Note: The <context:component-scan> element also implicitly defines the <context:annotation-config> autowiring element as well - after all if you are scanning for annotated @Component classes you want the embedded @Autowired annotations to be scanned for as well.

Part 4 can be found here

Spring Autowiring & Component Scanning Problems - Part 2: Component Scanning

Part 1 can be found here

Instead of adding explicit beans to your XML files, Spring 2.5 introduced the @Component annotation family (@Service, @Controller, @Repository – all children of the @Component parent annotation). Simply add these object-level annotations to your class definitions to mark what type of Spring bean they are. Then add the following XML snippet to the application context XML file to tell Spring where to look:

<context:component-scan base-package="com.andrewbeacock"/>
Spring now scans through the whole classpath for the specified package (and sub-packages) looking for @Component-based classes. Any found are created as beans and placed in the application context.

This purely adds the beans to the relevant application context, it doesn't look inside the class for other annotations until it's finished loading all the remaining beans into the context.

Part 3 can be found here

Spring Autowiring & Component Scanning Problems - Part 1: The Problem

Let's set the scene a little: You're a developer on a long-running Spring-based web application. It's a reasonably large application developed before annotations were a twinkle in Spring's eye and so uses XML to declare the beans and wiring. Over time the use of annotations has grown - particularly in the area of annotated controllers - and you've started to add @Autowired annotations rather than explicitly defining the wiring in the XML application context files.

So now you've got a good mix of XML-defined beans and annotated ones, sometimes mixing the two together; a bean is declared in the XML context file but it's wirings are defined using @Autowired statements rather than the usual XML elements.

Everything is working perfectly...

You've never had a problem adding @Autowired annotations to beans until now, but a particular bean's members don't seem to get wired (you get a NullPointerException at runtime) but you don't get a wiring error. This is confusing as you know that the @Autowired annotation has 'required' set to true by default, so it should be throwing a wiring exception during the loading of the context at the very least!

Why is it not wiring correctly? Because Spring is not even seeing the @Autowired annotation! To fully understand the issues at hand we need to wind back a bit and cover some theory.

Part 2 can be found here

Something new for my blog

I'm going to try something new, a multi-post feature which is basically an article I've written for an open source journal but broken up into bite-sized pieces and posted over a couple of weeks (or so).

Please comment if you like it, find it annoying, my content is completely wrong, etc. I'd like to hear from you.

My series is on "Spring Autowiring & Component Scanning Problems"