In this article, I write down how I made Spring 4 to generate beans with some given parameter. It’s worth doing that, because I had to read various parts of the official documentation and some blog posts, avoid the pages that refer to old version of Spring, and finally do some trial and error cycle to see how the pieces get together.

Purpose: instance some bean, whose behaviour changes depending on one or more parameters, passed by clients at creation time.

This is the used test bean:

public interface MyBean {
	public void work();
}
public class SimpleMyBean implements MyBean {
	private Integer num;
	public SimpleMyBean(Integer num) {
		super();
		this.num = num;
	}
	@Override
	public void work() {
		System.out.println(num + " -> " + toString());
	}
}

And now the solution, implemented on Java 6 + Spring 4.1, using the Java Config approach.

This is the developed configuration class:

@Configuration
public class AppConf {
	@Bean(name = "myBean")
	@Scope("prototype")
	public MyBean getMyBean(Integer num) {
		return new SimpleMyBean(num);
	}
}

it’s worth noting that:

  • the scope MUST be prototype, because logically many beans could be instantiated by this method and because, if not, Spring will throw a big error stack trace on bean initialization;
  • every getMyBean call creates a brand new instance, even if called with the same arguments, so if you desire to cache the instances then you should do within the method (or in methods it uses).

Finally, a nice main to test the whole thing:

public class Main {
	private ApplicationContext context;
	public static void main(String[] args) {
		Main instance = new Main();
		instance.execute();
	}
	private void execute() {
		context = new AnnotationConfigApplicationContext(AppConf.class);
		MyBean bean1 = context.getBean(MyBean.class, Integer.valueOf(10));
		bean1.work();
		MyBean bean2 = context.getBean(MyBean.class, Integer.valueOf(11));
		bean2.work();
		MyBean bean3 = context.getBean(MyBean.class, Integer.valueOf(10));
		bean3.work();
	}
}

that produces the following output (few words are cut out):

10 -> SimpleMyBean@38ee6681
11 -> SimpleMyBean@2b8bbc5a
10 -> SimpleMyBean@62facf0b

This output shows just that three instances have been generated.

Final notes

  • I think that a possible instance caching (to return the same instance when using the same arguments) should be implemented internally to the @Bean method. At least, I didn’t find any other method: a custom Scope implementation can’t resolve this issue.
  • Searching the net, many results suggest to develop a custom BeanFactory, but this method is deprecated in Spring 4.
  • The bean request method accepts arguments as Object array; the @Bean method of the @Configuration class may specify arguments with the type actually used (like Integer, in the example).
Annunci