DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
  1. DZone
  2. Coding
  3. Frameworks
  4. Injecting Spring beans into non-managed objects

Injecting Spring beans into non-managed objects

Jakub Kubrynski user avatar by
Jakub Kubrynski
·
Sep. 24, 13 · Interview
Like (1)
Save
Tweet
Share
22.13K Views

Join the DZone community and get the full member experience.

Join For Free
Advantages coming from dependency injection can be addictive. 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> {

  @Autowired
  private AutowireCapableBeanFactory autowireBeanFactory;

  public T createBean() {
    // creation logic
    autowireBeanFactory.autowireBean(createdBean);
    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:
@Configurable
public class MyCustomButton extends Button {

  @Autowired
  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:
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjrt</artifactId>
  <version>1.7.3</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aspects</artifactId>
  <version>3.2.4.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-tx</artifactId>
  <version>3.2.4.RELEASE</version>
</dependency>
<dependency>
  <groupId>javax.persistence</groupId>
  <artifactId>persistence-api</artifactId>
  <version>1.0</version>
  <scope>provided</scope>
</dependency>

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.
<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>aspectj-maven-plugin</artifactId>
  <version>1.5</version>
  <configuration>
    <source>1.7</source>
    <target>1.7</target>
    <complianceLevel>1.7</complianceLevel>
    <showWeaveInfo>true</showWeaveInfo>
    <aspectLibraries>
      <aspectLibrary>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
      </aspectLibrary>
    </aspectLibraries>
  </configuration>
  <executions>
    <execution>
      <goals>
        <goal>compile</goal>
      </goals>
    </execution>
  </executions>
</plugin>
And that's all folks :)
Spring Framework Object (computer science)

Published at DZone with permission of Jakub Kubrynski, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Why Does DevOps Recommend Shift-Left Testing Principles?
  • Explainer: Building High Performing Data Product Platform
  • Writing a Modern HTTP(S) Tunnel in Rust
  • Why Open Source Is Much More Than Just a Free Tier

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: