KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > beans > factory > annotation > RequiredAnnotationBeanPostProcessor


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.beans.factory.annotation;
18
19 import java.beans.PropertyDescriptor JavaDoc;
20 import java.lang.annotation.Annotation JavaDoc;
21 import java.lang.reflect.Method JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.List JavaDoc;
24
25 import org.springframework.beans.BeansException;
26 import org.springframework.beans.PropertyValues;
27 import org.springframework.beans.factory.BeanInitializationException;
28 import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
29 import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
30 import org.springframework.core.annotation.AnnotationUtils;
31 import org.springframework.util.Assert;
32
33 /**
34  * A {@link BeanFactoryPostProcessor} implementation that ensures that JavaBean
35  * properties on beans that are marked with an (arbitrary) {@link Annotation}
36  * are actually (configured to be) dependency-injected with a value.
37  *
38  * <p>The motivation for the existence of this BeanPostProcessor is to allow
39  * developers to annotate the setter properties of their own classes with an
40  * arbitrary JDK 1.5 annotation to indicate that the container must check
41  * for the configuration of a dependency injected value. This neatly pushes
42  * responsibility for such checking onto the container (where it arguably belongs),
43  * and obviates the need (<b>in part</b>) for a developer to code a method that
44  * simply checks that all required properties have actually been set.
45  *
46  * <p>Please note that an 'init' method may still need to implemented (and may
47  * still be desirable), because all that this class does is enforce that a
48  * 'required' property has actually been configured with a value. It does
49  * <b>not</b> check anything else... in particular, it does not check that a
50  * configured value is not <code>null</code>.
51  *
52  * @author Rob Harrop
53  * @author Juergen Hoeller
54  * @since 2.0
55  * @see Required
56  */

57 public class RequiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
58
59     private Class JavaDoc<? extends Annotation JavaDoc> requiredAnnotationType = Required.class;
60
61
62     /**
63      * Set the 'required' annotation type.
64      * The default required annotation type is the {@link Required} annotation.
65      * <p>This setter property exists so that developers can provide their own
66      * (non-Spring-specific) annotation type to indicate that a property value
67      * is required.
68      * @param requiredAnnotationType the desired annotation type
69      */

70     public void setRequiredAnnotationType(Class JavaDoc<? extends Annotation JavaDoc> requiredAnnotationType) {
71         Assert.notNull(requiredAnnotationType, "'requiredAnnotationType' must not be null");
72         this.requiredAnnotationType = requiredAnnotationType;
73     }
74
75     /**
76      * Return the 'required' annotation type.
77      */

78     protected Class JavaDoc<? extends Annotation JavaDoc> getRequiredAnnotationType() {
79         return this.requiredAnnotationType;
80     }
81
82
83     public PropertyValues postProcessPropertyValues(
84             PropertyValues pvs, PropertyDescriptor JavaDoc[] pds, Object JavaDoc bean, String JavaDoc beanName)
85             throws BeansException {
86
87         List JavaDoc<String JavaDoc> invalidProperties = new ArrayList JavaDoc<String JavaDoc>();
88         for (PropertyDescriptor JavaDoc pd : pds) {
89             if (isRequiredProperty(pd) && !pvs.contains(pd.getName())) {
90                 invalidProperties.add(pd.getName());
91             }
92         }
93         if (!invalidProperties.isEmpty()) {
94             throw new BeanInitializationException(buildExceptionMessage(invalidProperties, beanName));
95         }
96         return pvs;
97     }
98
99     /**
100      * Is the supplied property required to have a value (that is, to be dependency-injected)?
101      * <p>This implementation looks for the existence of a
102      * {@link #setRequiredAnnotationType "required" annotation}
103      * on the supplied {@link PropertyDescriptor property}.
104      * @param propertyDescriptor the target PropertyDescriptor (never <code>null</code>)
105      * @return <code>true</code> if the supplied property has been marked as being required;
106      * <code>false</code> if not, or if the supplied property does not have a setter method
107      */

108     protected boolean isRequiredProperty(PropertyDescriptor JavaDoc propertyDescriptor) {
109         Method JavaDoc setter = propertyDescriptor.getWriteMethod();
110         return (setter != null && AnnotationUtils.getAnnotation(setter, getRequiredAnnotationType()) != null);
111     }
112
113     /**
114      * Build an exception message for the given list of invalid properties.
115      * @param invalidProperties the list of names of invalid properties
116      * @param beanName the name of the bean
117      * @return the exception message
118      */

119     private String JavaDoc buildExceptionMessage(List JavaDoc<String JavaDoc> invalidProperties, String JavaDoc beanName) {
120         int size = invalidProperties.size();
121         StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
122         sb.append(size == 1 ? "Property" : "Properties");
123         for (int i = 0; i < size; i++) {
124             String JavaDoc propertyName = invalidProperties.get(i);
125             if (i > 0) {
126                 if (i == (size - 1)) {
127                     sb.append(" and");
128                 }
129                 else {
130                     sb.append(",");
131                 }
132             }
133             sb.append(" '").append(propertyName).append("'");
134         }
135         sb.append(size == 1 ? " is" : " are");
136         sb.append(" required for bean '").append(beanName).append("'");
137         return sb.toString();
138     }
139
140 }
141
Popular Tags