Refactor to use the application context as the source of Validators. This is appropriate as manual control over Validator instance creation and wiring is often necessary (not autowiring). This is particularly the case when dealing with DefaultAdvisorAutoProxyCreator, which excludes collaborating beans from being advice candidates.
This commit is contained in:
parent
018f625e85
commit
5fdcbe1ec4
|
@ -15,46 +15,24 @@
|
|||
|
||||
package net.sf.acegisecurity.domain.validation;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import org.springframework.validation.Validator;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* A basic implementation of {@link ValidationRegistryManager}.
|
||||
*
|
||||
* <p>
|
||||
* Like <a
|
||||
* href="http://java.sun.com/j2se/1.4.2/docs/api/java/beans/PropertyEditorManager.html">PropertyEditorManager</a>,
|
||||
* this implementation uses three techniques for locating a
|
||||
* <code>Validator</code> for a given domain object class:
|
||||
*
|
||||
* <ol>
|
||||
* <li>
|
||||
* First, the {@link #registerValidator(Class, Class)} method allows a
|
||||
* <code>Validator</code> to be expressly registered for a given domain object
|
||||
* class.
|
||||
* </li>
|
||||
* <li>
|
||||
* Second, an attempt will be made to find the <code>Validator</code> by
|
||||
* concatenating "Validator" to the fully qualified domain object classname
|
||||
* (eg "foo.bah.PersonValidator").
|
||||
* </li>
|
||||
* <li>
|
||||
* Third, it takes the domain object's simple classname (without the package
|
||||
* name), adds "Validator" to it, then looks in the {@link
|
||||
* #validatorSearchPath} for the validator.
|
||||
* </li>
|
||||
* </ol>
|
||||
* Locates <code>Validator</code>s registered in bean factory.
|
||||
* </p>
|
||||
*
|
||||
* @author Matthew E. Porter
|
||||
|
@ -65,115 +43,53 @@ public class ValidationRegistryManagerImpl implements ValidationRegistryManager,
|
|||
BeanFactoryAware {
|
||||
//~ Static fields/initializers =============================================
|
||||
|
||||
private static final String VALIDATOR_SUFFIX = "Validator";
|
||||
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private AutowireCapableBeanFactory acbf;
|
||||
private ListableBeanFactory bf;
|
||||
private Map validatorMap = new HashMap();
|
||||
private String[] validatorSearchPath;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory)
|
||||
throws BeansException {
|
||||
Assert.isInstanceOf(AutowireCapableBeanFactory.class, beanFactory,
|
||||
"BeanFactory must be AutowireCapableBeanFactory");
|
||||
this.acbf = (AutowireCapableBeanFactory) beanFactory;
|
||||
}
|
||||
|
||||
public void setValidatorSearchPath(String[] validatorSearchPath) {
|
||||
this.validatorSearchPath = validatorSearchPath;
|
||||
}
|
||||
|
||||
public String[] getValidatorSearchPath() {
|
||||
return validatorSearchPath;
|
||||
Assert.isInstanceOf(ListableBeanFactory.class, beanFactory,
|
||||
"BeanFactory must be ListableBeanFactory");
|
||||
this.bf = (ListableBeanFactory) beanFactory;
|
||||
}
|
||||
|
||||
public Validator findValidator(Class domainClass) {
|
||||
Assert.notNull(domainClass, "domainClass cannot be null");
|
||||
|
||||
Class validatorClass = null;
|
||||
Validator validator = null;
|
||||
|
||||
if (validatorMap.containsKey(domainClass)) {
|
||||
// already known to our Map
|
||||
validatorClass = (Class) validatorMap.get(domainClass);
|
||||
} else {
|
||||
validatorClass = this.findValidatorClass(domainClass.getName()
|
||||
+ VALIDATOR_SUFFIX);
|
||||
|
||||
if (validatorClass == null) {
|
||||
String suffix = "." + ClassUtils.getShortName(domainClass)
|
||||
+ VALIDATOR_SUFFIX;
|
||||
|
||||
if (validatorSearchPath != null) {
|
||||
for (int i = 0;
|
||||
(i < validatorSearchPath.length)
|
||||
&& (validatorClass == null); i++) {
|
||||
validatorClass = this.findValidatorClass(validatorSearchPath[i]
|
||||
+ suffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we found a Validator, register it so we speed up future retrieval
|
||||
if (validatorClass != null) {
|
||||
this.registerValidator(domainClass, validatorClass);
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to create an instance of the Validator
|
||||
if (validatorClass != null) {
|
||||
validator = obtainWiredValidator(validatorClass);
|
||||
}
|
||||
|
||||
return validator;
|
||||
if (validatorMap.containsKey(domainClass)) {
|
||||
if (validatorMap.get(domainClass) == null) {
|
||||
return null;
|
||||
}
|
||||
return (Validator) this.bf.getBean((String)validatorMap.get(domainClass), Validator.class);
|
||||
}
|
||||
|
||||
// Attempt to find Validator via introspection
|
||||
Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(bf, Validator.class, true, true);
|
||||
Iterator iter = beans.keySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
String beanName = (String) iter.next();
|
||||
Validator validator = (Validator) beans.get(beanName);
|
||||
if (validator.supports(domainClass)) {
|
||||
this.validatorMap.put(domainClass, beanName);
|
||||
return validator;
|
||||
}
|
||||
}
|
||||
|
||||
// No Validator found
|
||||
this.validatorMap.put(domainClass, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
public void registerValidator(Class domainClass, Class validatorClass) {
|
||||
public void registerValidator(Class domainClass, String beanName) {
|
||||
Assert.notNull(domainClass, "domainClass cannot be null");
|
||||
Assert.notNull(validatorClass, "validatorClass cannot be null");
|
||||
Assert.isTrue(Validator.class.isAssignableFrom(validatorClass),
|
||||
"validatorClass must be an implementation of Validator");
|
||||
this.validatorMap.put(domainClass, validatorClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a new instance of the <code>Validator</code>.
|
||||
*
|
||||
* <p>
|
||||
* By default, the <code>AutowireCapableBeanFactory</code> is used to build
|
||||
* the instance, and autowire its bean properties. Specialised
|
||||
* applications may wish to customise this behaviour, such as searching
|
||||
* through the <code>ApplicationContext</code> for an existing singleton
|
||||
* instance. This method is protected to enable such customisation.
|
||||
* </p>
|
||||
*
|
||||
* @param clazz the represents the <code>Validator</code> instance required
|
||||
*
|
||||
* @return the requested <code>Validator</code>, fully wired with all
|
||||
* dependencies, or <code>null</code> if the
|
||||
* <code>Validator</code> could not be found or created
|
||||
*/
|
||||
protected Validator obtainWiredValidator(Class clazz) {
|
||||
try {
|
||||
return (Validator) this.acbf.autowire(clazz,
|
||||
AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
|
||||
} catch (BeansException autowireFailure) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Class findValidatorClass(String validatorClassName) {
|
||||
Class validatorClass = null;
|
||||
|
||||
try {
|
||||
ClassLoader contextClassLoader = Thread.currentThread()
|
||||
.getContextClassLoader();
|
||||
validatorClass = Class.forName(validatorClassName);
|
||||
} catch (ClassNotFoundException e) {}
|
||||
|
||||
return validatorClass;
|
||||
Assert.notNull(beanName, "beanName cannot be null");
|
||||
Assert.isTrue(this.bf.containsBean(beanName), "beanName not found in context");
|
||||
Assert.isInstanceOf(Validator.class, this.bf.getBean(beanName), "beanName '" + beanName + "' must be a Validator");
|
||||
Assert.isTrue(((Validator)this.bf.getBean(beanName)).supports(domainClass), "Validator does not support " + domainClass);
|
||||
this.validatorMap.put(domainClass, beanName);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue