Skip to content

Autowiring of @Required spring bean properties

by on June 27, 2014

Spring 2.0 introduced @Required, Spring 2.5 added @Autowired and Spring 3.0 added even more annotation driven configuration capabilities by introducing @Configuration and added support for JSR 330 annotations. So given a legacy bean of type A whose properties are annotated with @Required we might want to derive a more modern-style spring bean using @Named and @Inject. The problem now is that we can’t simply extend class A like that:

@Named("fail")
public class B extends A {
    ...
}

By default, springs RequiredAnnotationBeanPostProcessor would raise an exception when processing the bean named "fail". So we should either think about using delegation instead of inheritance – thus using two separately defined beans like outlined below:

@Named("delegate")
public class B {
    @Inject private A a;
    ...
}

If we can’t resort to delegation for some reason, the following configuration class can solve our problem:

@Configuration public class TestConfiguration {

  @Inject private ConfigurableListableBeanFactory beanFactory;

  @Bean(autowire = Autowire.BY_TYPE)
  public BeanWithAutowiredProperties beanWithAutowiredProperties() {
    AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
    autowiredAnnotationBeanPostProcessor.setAutowiredAnnotationType(Required.class);
    autowiredAnnotationBeanPostProcessor.setBeanFactory(beanFactory);
    BeanWithAutowiredProperties beanWithAutowiredProperties = new BeanWithAutowiredProperties();
    autowiredAnnotationBeanPostProcessor.processInjection(beanWithAutowiredProperties);
    return beanWithAutowiredProperties;
  }

  @Bean public BeanWithAutowiredProperties fail(){
    return new BeanWithAutowiredProperties();
  }

  @Named public static class A {  }

  @Named public static class B {  }

  public static class LegacyBean {

    private A a;

    public A getA() {
      return a;
    }

    @Required public void setA(A a) {
      this.a = a;
    }
  }

  public static class BeanWithAutowiredProperties extends LegacyBean {

    private B b;

    public B getB() {
      return b;
    }

    public void setB(B b) {
      this.b = b;
    }

    @PostConstruct void initialize(){
      if(null == getA()) {
        throw new IllegalStateException("required property must not be null");
      }
      if(null == b) {
        throw new IllegalStateException("autowired must not be null");
      }
    }
  }

}

Note that we’re using a local bean post processor so that the spring lifecycle for other beans is not affected.

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s