Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (5.49 MB, 753 trang )
9799ch03.qxd
56
5/5/08
4:50 PM
Page 56
CHAPTER 3 ■ BEAN CONFIGURATION IN SPRING
Table 3-1. Dependency Checking Modes Supported by Spring
Mode
Description
none*
No dependency checking will be performed. Any properties can be left unset.
simple
If any properties of the simple types (the primitive and collection types) have not been
set, an UnsatisfiedDependencyException will be thrown.
objects
If any properties of the object types (other than the simple types) have not been set, an
UnsatisfiedDependencyException will be thrown.
all
If any properties of any type have not been set, an UnsatisfiedDependencyException
will be thrown.
* The default mode is none, but this can be changed by setting the default-dependency-check attribute of the
this attribute with great care as it will alter the default dependency checking mode for all the beans in the
IoC container.
How It Works
Checking Properties of the Simple Types
Suppose the suffix property was not set for the sequence generator. Then the generator
would generate sequence numbers whose suffix was the string null. This kind of issue is often
very hard to debug, especially in a complicated bean. Fortunately, Spring is able to check if all
properties of certain types have been set. To ask Spring to check properties of the simple types
(i.e., the primitive and collection types), set the dependency-check attribute of
simple.
class="com.apress.springrecipes.sequence.SequenceGenerator"
dependency-check="simple">
If any properties of such types have not been set, an UnsatisfiedDependencyException will
be thrown, indicating the unset property.
Exception in thread "main"
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating
bean with name 'sequenceGenerator' defined in class path resource [beans.xml]:
Unsatisfied dependency expressed through bean property 'suffix': Set this property
value or disable dependency checking for this bean.
9799ch03.qxd
5/5/08
4:50 PM
Page 57
CHAPTER 3 ■ BEAN CONFIGURATION IN SPRING
Checking Properties of the Object Types
If the prefix generator is not set, then the evil NullPointerException will be thrown when prefix generation is requested. To enable dependency checking for bean properties of object
types, (i.e., other than simple types), change the dependency-check attribute to objects.
class="com.apress.springrecipes.sequence.SequenceGenerator"
dependency-check="objects">
Then when you run the application, Spring will notify you that the prefixGenerator property has not been set.
Exception in thread "main"
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating
bean with name 'sequenceGenerator' defined in class path resource [beans.xml]:
Unsatisfied dependency expressed through bean property 'prefixGenerator': Set this
property value or disable dependency checking for this bean.
Checking Properties of All Types
If you would like to check all bean properties whatever the type is, you can change the
dependency-check attribute to all.
class="com.apress.springrecipes.sequence.SequenceGenerator"
dependency-check="all">
Dependency Checking and Constructor Injection
Spring’s dependency checking feature will only check if a property has been injected via the
setter method. So, even if you have injected the prefix generator via a constructor, an
UnsatisfiedDependencyException will still be thrown.
class="com.apress.springrecipes.sequence.SequenceGenerator"
dependency-check="all">
57
9799ch03.qxd
58
5/5/08
4:50 PM
Page 58
CHAPTER 3 ■ BEAN CONFIGURATION IN SPRING
3-6. Checking Properties with the @Required Annotation
Problem
Spring’s dependency checking feature can only check for all properties of certain types. It’s not
flexible enough to check for particular properties only. In most cases, you would like to check
if particular properties have been set, but not all properties of certain types.
Solution
RequiredAnnotationBeanPostProcessor is a Spring bean post processor that checks if all the
bean properties with the @Required annotation have been set. A bean post processor is a special kind of Spring bean that is able to perform additional tasks on each bean before its
initialization. To enable this bean post processor for property checking, you must register it
in the Spring IoC container. Note that this processor can only check if the properties have
been set, but can’t check if their value is not null.
How It Works
Suppose that both the prefixGenerator and suffix properties are required for a sequence
generator. You can annotate their setter methods with @Required.
package com.apress.springrecipes.sequence;
import org.springframework.beans.factory.annotation.Required;
public class SequenceGenerator {
private PrefixGenerator prefixGenerator;
private String suffix;
...
@Required
public void setPrefixGenerator(PrefixGenerator prefixGenerator) {
this.prefixGenerator = prefixGenerator;
}
@Required
public void setSuffix(String suffix) {
this.suffix = suffix;
}
...
}
To ask Spring to check if these properties have been set on all sequence generator
instances, you have to register a RequiredAnnotationBeanPostProcessor instance in the IoC
container. If you are using a bean factory, you have to register this bean post processor
through the API. Otherwise, you can just declare an instance of this bean post processor in
your application context.
9799ch03.qxd
5/5/08
4:50 PM
Page 59
CHAPTER 3 ■ BEAN CONFIGURATION IN SPRING
If you are using Spring 2.5, you can simply include the
element in your bean configuration file, and a RequiredAnnotationBeanPostProcessor instance
will automatically get registered.
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">
...
If any properties with @Required have not been set, a BeanInitializationException will be
thrown by this bean post processor.
Exception in thread "main" org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'sequenceGenerator' defined in class path resource
[beans.xml]: Initialization of bean failed; nested exception is
org.springframework.beans.factory.BeanInitializationException: Property
'prefixGenerator' is required for bean 'sequenceGenerator'
In addition to the @Required annotation, RequiredAnnotationBeanPostProcessor can also
check the properties with your custom annotation. For example, you can create the following
annotation type:
package com.apress.springrecipes.sequence;
...
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Mandatory {
}
And then you can apply this annotation to the setter methods of the required properties.
package com.apress.springrecipes.sequence;
public class SequenceGenerator {
private PrefixGenerator prefixGenerator;
private String suffix;
...
@Mandatory
59