Chariot Training Classes

Training Courses

I run Chariot's training and mentoring services. We provide training in AngularJS, HTML5, Spring, Hibernate, Maven, Scala, and more.

Chariot Education Services

Technology

Chariot Emerging Tech

Learn about upcoming technologies and trends from my colleagues at Chariot Solutions.

Resources

Chariot Conferences

Podcasts

« Adding deeper logging to Webflow Exceptions | Main | Bug fix in 1 day?? WOW, ROO TEAM! »
Monday
Feb212011

Spring Corner - What are those Post Processor Beans anyway?

This is the first in an occasional series of tutorials and tips about the Spring Framework.

Hey there, Spring Fans! Ever look into your Spring configuration files and see beans that end in the name PostProcessor? What does that mean? And more importantly, why should I care?

The Spring Container Lifecycle

When you mount an application context, Spring starts up, following a predictable lifecycle. The actions it performs are:

  1. Load all bean definitions before constructing beans
  2. Construct each bean via reflection
  3. Inject components via setters, autowired methods, etc...
  4. Post-process the bean
  5. Make the bean available for use by injection or direct lookup
Obviously we're going to focus on that post-processing step. It turns out Post Processing allows Spring's magic to happen.

Bean Post Processors

There are a number of pre-defined post processor beans. For example, the RequiredAnnotationPostProcessor looks for any beans annotated with the @Required annotation, and if the property isn't set during startup, the post processor will throw an exception and stop the startup of the container. From the definition:

  for (PropertyDescriptor pd : pds) {
      if (isRequiredProperty(pd) && !pvs.contains(pd.getName())) {
         invalidProperties.add(pd.getName());
      }
  }
  if (!invalidProperties.isEmpty()) {
     throw new BeanInitializationException(
         buildExceptionMessage(invalidProperties, beanName));
  }

Why are BeanPostProcessors important?

Spring uses BeanPostProcessors everywhere to enable features such as security, transaction processing, remoting, JMX monitoring, and a number of other features. Besides mounting a bean directly, you install these post-processors when you use certain Spring namespace features. For example:

  <tx:annotation-driven>
This statement mounts a bean post processor that watches your beans for the @Transactional annotation, and wraps the beans in a proxy class that watches calls to methods, and coordinates with the Spring transaction manager.

Post-processing your own code

You can write your own bean post processor to inspect a newly-created bean, and potentially modify it or return another bean entirely. There are a number of ways to do this, starting with implementing BeanPostProcessor.

Startup Methods

A simpler way to initiate an on-startup process that is Spring 3.0 and annotation friendly is to mount a bean post processor known as the CommonAnnotationPostProcessor bean and use the @PostConstruct Java EE annotation on a method in your class. For example:

@Component
public class MyServiceBean implements MyService {

  @PostConstruct
  public void initialize() {
     // do something here
  }
...
}

How to find out more...

Open up your favorite IDE (SpringSource Tool Suite is great for this) and lookup the source for BeanPostProcessor. Ask the IDE to show you all implementing classes - of which there are a lot. Here is another example - the BeanValidationPostProcessor which implements JSR-303 Java EE Bean Validation on methods annotated with @Valid:

public Object postProcessAfterInitialization(Object bean, String beanName) 
                                             throws BeansException {
  if (this.afterInitialization) {
    doValidate(bean);
  }
  return bean;
}
...

protected void doValidate(Object bean) {
  Set<ConstraintViolation<Object%gt;%gt; result = this.validator.validate(bean);
  if (!result.isEmpty()) {
    StringBuilder sb = new StringBuilder("Bean state is invalid: ");
    for (Iterator%lt;ConstraintViolation%lt;Object%gt;%gt; 
         it = result.iterator(); it.hasNext();) {
      ConstraintViolation<Object> violation = it.next();
      sb.append(violation.getPropertyPath()).append(" - ")
                                            .append(violation.getMessage());
      if (it.hasNext()) {
          sb.append("; ");
      }
    }
    throw new BeanInitializationException(sb.toString());
  }
}

Because Spring is open source, you can easily read and even debug source code in the framework. Use this to your advantage, and really dig in and learn how it operates. If you use Spring Roo, you can even have an entire application platform built for you, including source-code pathing from Maven repositories, so you can just look up the classes and see the source code.

About the author

Ken Rimple lives, breathes, and eats Spring code for a living. He is a developer, mentor and educator, teaching SpringSource courses such as Core Spring, Hibernate with Spring and Spring Rich Web Applications for Chariot Solutions, a VMWare/SpringSource Authorized Training Center and consulting partner. You can find Chariot's course schedule, which also includes courses on Maven, at chariotsolutions.com/education.

PrintView Printer Friendly Version

EmailEmail Article to Friend

Reader Comments

There are no comments for this journal entry. To create a new comment, use the form below.

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>