Archive

Posts Tagged ‘di’

Spring can inject Servlets too!

September 28th, 2009 1 comment

In this article, I will show you that Spring dependency injection mechanism is not restricted solely to Spring-managed beans, that is Spring can inject its beans in objects created by the new keywords, servlets instantiated in the servlet container, and pretty anything you like. Spring classical mode is to be an object factory. That is, Spring creates anything in your application, using the provided constructor. Yet, some of the objects you use are outer Spring’s perimeter. Two simple examples:

  • servlets are instantiated by the servlet container. As such, they cannot be injected out-of-the-box
  • some business objects are not parameterized in Spring but rather created by your own code with the new keyword

Both these examples show you can’t delegate to Spring every object instantiation.

There was a time when I foolishly thought Spring was a closed container. Either your beans were managed by Spring, or they didn’t: if they were, you could inject them with other Spring-managed beans. If they weren’t, tough luck! Well, this is dead wrong. Spring can inject its beans into pretty much anything provided you’re okay to use AOP.

In order to do this, there are only 2 steps to take:

Use AOP

It is done in your Spring configuration file.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.0.xsd


http://www.springframework.org/schema/context

	http://www.springframework.org/schema/context/spring-context-2.5.xsd">

  <This does the magic />
  <context:spring-configured />

  <-- These are for classical annotation configuration -->
  <context:annotation-config />
  <context:component-scan base-package="ch.frankel.blog.spring.outcontainer" />

</beans>

You need also configure which aspect engine to use to weave the compiled bytecode. In this cas, it is AspectJ, which is the AOP component used by Spring. Since i’m using Maven as my build tool of choice, this is easily done in my POM. Ant users will have to do it in their build.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    http://maven.apache.org/maven-v4_0_0.xsd">
...
  <properties>
    <spring-version>2.5.6.SEC01</spring-version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>${spring-version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>${spring-version}</version>
    </dependency>
    <dependency>
      <groupId>aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.5.4</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>aspectj-maven-plugin</artifactId>
        <configuration>
          <complianceLevel>1.5</complianceLevel>
          <aspectLibraries>
            <aspectLibrary>
              <groupId>org.springframework</groupId>
              <artifactId>spring-aspects</artifactId>
            </aspectLibrary>
          </aspectLibraries>
        </configuration>
        <executions>
          <execution>
            <goals>
              <goal>compile</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

Configure which object creation to intercept

This is done with the @org.springframework.beans.factory.annotation.Configurable annotation on your injectable object.

@Configurable
public class DomainObject {

  /** The object to be injected by Spring. */
  private Injectable injectable;

  public Injectable getInjectable() {

    return injectable;
  }

  @Autowired
  public void setInjectable(Injectable injectable) {

    this.injectable = injectable;
  }
}

Now with only these few lines of configuration (no code!), I’m able to inject Spring-managed beans into my domain object. I leave to you to implement the same with regular servlets (which are much harder to display as unit test).

You can find the Maven project used for this article here. The unit test packaged shows the process described above.

To go further:

Send to Kindle

Simplest Java decoupling without 3rd party frameworks

March 21st, 2009 1 comment

“[...] coupling (or dependency) is the degree to which each program module relies on each one of the other modules.”

From Wikipedia

In object-oriented programming, removing dependencies is done by using interface. Thus, if class A is dependent on class B, we introduce interface C, which is implemented by B. Now A depends on C  (see below).

This first step in decoupling is called programming by interface. Read more…

Send to Kindle