Spring can do dependency checking to make sure the required properties have been set or injected.
Spring supports four dependency checking modes.
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 + "]"; } }
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.
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.
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.
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'
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>