Spring Tutorial - Spring Dependency Check








Spring can do dependency checking to make sure the required properties have been set or injected.

Spring supports four dependency checking modes.

  • none - No dependency checking. Default mode.
  • simple - If any properties of primitive type (int, long, double...) and collection types (map, list...) have not been set, Spring throws UnsatisfiedDependencyException.
  • objects - If any properties of object type have not been set, Spring will throw UnsatisfiedDependencyException.
  • all - If any properties of any type have not been set, Spring will throw an UnsatisfiedDependencyException.




Java Bean

The following sections uses the two Java bean as follows to shows how to use the dependency checking.

Customer class.

package com.java2s.common;

public class Customer {
  private Person person;
  private int type;
  private String action;

  public Person getPerson() {
    return person;
  }

  public void setPerson(Person person) {
    this.person = person;
  }

  public int getType() {
    return type;
  }

  public void setType(int type) {
    this.type = type;
  }

  public String getAction() {
    return action;
  }

  public void setAction(String action) {
    this.action = action;
  }

  @Override
  public String toString() {
    return "Customer [person=" + person + ", type=" + type + ", action="
        + action + "]";
  }
}

Person class

package com.java2s.common;

public class Person 
{
    private String name;
    private String address;
    private int age;
    public String getName() {
      return name;
    }
    public void setName(String name) {
      this.name = name;
    }
    public String getAddress() {
      return address;
    }
    public void setAddress(String address) {
      this.address = address;
    }
    public int getAge() {
      return age;
    }
    public void setAge(int age) {
      this.age = age;
    }
  @Override
  public String toString() {
    return "Person [name=" + name + ", address=" + address + ", age=" + age
        + "]";
  }
    
}




dependency checking:none

The following code shows how to use spring bean configuration file with 'none' dependency checking mode.

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
  <bean id="myCustomer" class="com.java2s.common.Customer" >
    <property name="action" value="buy" />
  </bean>
  <bean id="myPerson" class="com.java2s.common.Person">
    <property name="name" value="java2s" />
    <property name="address" value="address ABC" />
    <property name="age" value="29" />
  </bean>
</beans>

The default value to dependency checking is none. If you did not explicitly define the dependency checking mode, it's default to 'none'. Therefore no dependency checking will perform.

dependency checking:simple

The following code shows how to use Spring bean configuration file with 'simple' dependency checking mode.

  <bean id="myCustomer" class="com.java2s.common.Customer" 
         dependency-check="simple">

Full configuration file.

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
  <bean id="myCustomer" class="com.java2s.common.Customer" 
         dependency-check="simple">
    <property name="person" ref="myPerson" />
    <property name="action" value="buy" />
  </bean>
  <bean id="myPerson" class="com.java2s.common.Person">
    <property name="name" value="java2s" />
    <property name="address" value="address ABC" />
    <property name="age" value="29" />
  </bean>
</beans>

In the xml code above the myCustomer bean is marked to use simple dependency check. For the simple dependency check, if any properties of primitive type (int, long, double...) and collection types (map, list...) have not been set, Spring throws UnsatisfiedDependencyException.

The 'type' property is type int which is a primitive type has not been set, an UnsatisfiedDependencyException will throw as follows.

Spring dependency checking with @Required Annotation

In the following we will introducing another way of doing dependency checking.

We can use @Required Annotation to add dependency checking for Java beans.

@Required annotation can apply to a particular property.

The following Customer object has @Required in setPerson() method to make sure the person property has been set.

package com.java2s.common;
import org.springframework.beans.factory.annotation.Required;
public class Customer 
{
  private Person person;
  private int type;
  private String action;
  public Person getPerson() {
    return person;
  }
  @Required
  public void setPerson(Person person) {
    this.person = person;
  }
  public int getType() {
    return type;
  }
  public void setType(int type) {
    this.type = type;
  }
  public String getAction() {
    return action;
  }
  public void setAction(String action) {
    this.action = action;
  }
  
}

After applying the @Required annotation on the method, we also need to register an RequiredAnnotationBeanPostProcessor to acknowledge the @Required annotation in bean configuration file.

There are two ways to enable the RequiredAnnotationBeanPostProcessor.

  • Add Spring context and <context:annotation-config /> in bean configuration file.
  • Include 'RequiredAnnotationBeanPostProcessor' directly in bean configuration file.

Here is the syntax of context:annotation-config.

<context:annotation-config />

Full source code,

<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.5.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context-2.5.xsd">

  <context:annotation-config />

  <bean id="CustomerBean" class="com.java2s.common.Customer">
    <property name="action" value="buy" />
    <property name="type" value="1" />
  </bean>
  <bean id="PersonBean" class="com.java2s.common.Person">
    <property name="name" value="java2s" />
    <property name="address" value="address ABC" />
    <property name="age" value="29" />
  </bean>
</beans>

The following xml code shows how to include 'RequiredAnnotationBeanPostProcessor' in bean configuration file.

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    <bean 
        class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
  <bean id="CustomerBean" class="com.java2s.common.Customer">
    <property name="action" value="buy" />
    <property name="type" value="1" />
  </bean>
  <bean id="PersonBean" class="com.java2s.common.Person">
    <property name="name" value="java2s" />
    <property name="address" value="address ABC" />
    <property name="age" value="29" />
  </bean>
</beans>

If we run it , the following error message will be throw, because person property is unset.

org.springframework.beans.factory.BeanInitializationException: 
  Property 'person' is required for bean 'CustomerBean'

Define Custom @Required-Style Annotation In Spring

We can define custom annotation to do dependency checking by using Spring @Required-style annotation.

In the following example, we will create a custom @Required-style annotation named @Mandatory, which is equivalent to @Required annotation.

First, we create the @Mandatory interface.

package com.java2s.common;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Mandatory {
}

Then, we apply the new created annotation to a property from a Java Bean.

package com.java2s.common;

public class Customer 
{
  private Person person;
  private int type;
  private String action;

  @Mandatory
  public void setPerson(Person person) {
    this.person = person;
  }
}

Finally, we need to register it in the xml configuration file by including @Mandatory annotation in 'RequiredAnnotationBeanPostProcessor' class.

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    <bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor">
      <property name="requiredAnnotationType" value="com.java2s.common.Mandatory"/>
    </bean>
  <bean id="CustomerBean" class="com.java2s.common.Customer">
    <property name="action" value="buy" />
    <property name="type" value="1" />
  </bean>
</beans>