Injecting Spring beans into non-managed objects

Advantages coming from dependency injection can be addicting. It's a lot easier to configure application structure using injections than doing all resolutions manually. It's hard to resign from it when we have some non-managed classes that are instantiated outside of the container - for example being part of other frameworks like Vaadin UI components or JPA entities. The latter are especially important when we're using Domain Driven Design. During DDD training ran by Slawek Sobotka we were talking about options to remove "bad coupling" from aggregate factories. I'm sure you'll admit, that it's better to have generic mechanism able to "energize" objects by dependencies defined by e.g. @Inject annotation than inject all necessary dependencies into particular factory and then pass them into object by constructor, builder or simple setters.

Spring framework brings us two different solutions to achieve such requirement. I'll now describe them both of them. Let's start with with simpler one.

It's especially powerful when we've case such as generic repository, mentioned earlier aggregate factory, or even any other factory just ensuring that we have only few places in our code where will instantiate objects outside of the container. In this case we can make use of AutowireCapableBeanFactory class. In particular we will be interested in two methods:
  • void autowireBean(Object existingBean)
  • Object initializeBean(Object existingBean, String beanName)
The first one just populates our bean without applying specific post processors (e.g. @PostConstruct, etc). The second one additionally applies factory callbacks like setBeanName and setBeanFactory, as well as any other post processors with @PostConstruct of course. In our code it'll look like this:
public abstract class GenericFactory<T> {

  private AutowireCapableBeanFactory autowireBeanFactory;

  public T createBean() {
    // creation logic
    return createdBean;
Simple and powerful - my favorite composition :)

But what can we do when we have plenty places in our code where objects get born? That's for example case of building Vaadin layouts in Spring web application. Injecting custom bean configurer objects invoking autowireBean method won't be the peak of productivity. Happily Spring developers brought us @Configurable annotation. This annotation connected with aspects will configure each annotated object even if we will create it outside of the container using new operator. Like with any other aspects we can choose between
  • load-time-waving (LTW)
  • compile-time-waving (CTW). 
The first one is easier to configure but we become (due to instrumentation) dependent from application server, which can be undesirable in some cases.  To use it we need to annotate our @Configuration class by @EnableLoadTimeWeaving (or add <context:load-time-weaver/> tag if you like Flintstones and XML configuration ;)) After completing configuration just annotate class by @Configurable:
public class MyCustomButton extends Button {

  private MyAwesomeService myAwesomeService;

  // handlers making use of injected service

The second option is a little bit more complex to setup but after this it will be a lot lighter in runtime. Because now we want to load aspects till compilation we have to integrate aspectj compiler into our build. In Maven you need to add few dependencies:

I hope you are curious why above you can see persistence-api. That was also strange for me, when I saw "can't determine annotations of missing type javax.persistence.Entity" error during aspectj compilation. The answer can be found in SpringFramework JIRA in issue SPR-6819. This happens when you configure spring-aspects as a aspectLibrary in aspectj-maven-plugin. Issue is unresolved for over three year so better get used to it :) The last thing we need to do is to include above-mentioned plugin into our plugins section.
And that's all folks :)


Anonymous said…
@Configurable(autowire = Autowire.BY_TYPE)
public class MyClass{

private SpringManagedType member;

Jakub Kubrynski said…
If you use @Autowired then you don't want to additionaly autowire by type - that's overlaping
Anonymous said…
Thanks, nice post
Daniel said…
I have a different approach for this:

Hi to every one, it's really a pleasant for me to go to see this site, it contains precious Information. yahoo login mail
Unknown said…
Thanks for sharing an informative blog keep rocking bring more details.I like the helpful info you provide in your articles. I’ll bookmark your weblog and check again here regularly. I am quite sure I will learn much new stuff right here! Good luck for the next!
mobile application development training online
mobile app development course
mobile application development course
learn mobile application development
mobile app development training
app development training
mobile application development training
mobile app development course online
online mobile application development
divi said…
awesome blog it's very nice and useful i got many more information it's really nice i like your blog styleweb design company in velachery
virgoacp said…
Aluminium Composite Panel or ACP Sheet is used for building exteriors, interior applications, and signage. They are durable, easy to maintain & cost-effective with different colour variants.
zuan said…
Thanks for sharing an informative blog keep rocking bring more details.I like the helpful info you provide in your articles. I’ll bookmark your weblog and check again here regularly. I am quite sure I will learn much new stuff right here! Good luck for the next!
web designer courses in chennai | best institute for web designing Classes in Chennai
mobile application development course | mobile app development training | mobile application development training online
web designing classes in chennai | web designing training institute in chennai
Web Designing Institute in Chennai | Web Designing Training in Chennai
website design course | Web designing course in Chennai

Popular posts from this blog

Understanding the first level JPA cache

Including Java agent in standalone Spring Boot application

Understanding Spring Web Initialization