`
movingboy
  • 浏览: 55002 次
社区版块
存档分类
最新评论

答复: acegi的objectDefinitionSource为什么可以接受string类型!??

    博客分类:
  • Java
阅读更多
曾经查看Acegi的源码,FilterSecurityInterceptor的objectDefinitionSource属性的类型为FilterInvocationDefinitionSource,猜测Acegi是使用FilterInvocationDefinitionSourceEditor读取配置并赋值给它(objectDefinitionSource)的,因为查看FilterInvocationDefinitionSourceEditor的源码,其中有相关的读取配置的代码。但FilterInvocationDefinitionSourceEditor是在何时及如何被调用的呢?

在Spring的官方论坛中找到一个帖子:http://forum.springframework.org/showthread.php?t=11242&highlight=objectDefinitionSource

其中提到:

引用
The PropertyEditorManager uses three techniques for locating an editor for a given type. First, it provides a registerEditor method to allow an editor to be specifically registered for a given type. Second it tries to locate a suitable class by adding "Editor" to the full qualified classname of the given type (e.g. "foo.bah.FozEditor"). Finally it takes the simple classname (without the package name) adds "Editor" to it and looks in a search-path of packages for a matching class.


PropertyEditorManager是java.beans包中的一个类,难道其中的根据“类型名称+Editor”来查找属性相应的编辑器(姑且这么翻译)的机制是Java早就拥有的?查看JDK中PropertyEditorManager相关的内容,果然找到上面的那段话!

原来是这样!难怪在Spring、Acegi的源码中都找不到注册或调用FilterInvocationDefinitionSourceEditor的代码。我以为这是Spring或Acegi提供的机制,原来是Java的标准机制!

至此可以理解读取配置并给属性赋值的过程大致如下:
1.Spring读取Acegi相关的配置,知道需要把类似

引用
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON 
                 PATTERN_TYPE_APACHE_ANT 
                 /secured/usermanage/**=ROLE_TEST 
                 /secured/**=ROLE_USER


的内容赋值给bean filterSecurityInterceptor的objectDefinitionSource属性

2.Spring知道filterSecurityInterceptor的objectDefinitionSource属性的类型为FilterInvocationDefinitionSource,查找该类型的编辑器。因为Acegi并未为该类型显式地注册编辑器(查Acegi代码可知),Spring应用上面的规则查到相应的编辑器为FilterInvocationDefinitionSourceEditor

3.Spring实例化FilterInvocationDefinitionSourceEditor,并调用它完成后续的读取配置并给属性赋值的工作
分享到:
评论
1 楼 truesmile 2009-08-17  
嗯,说的没错,开始贴代码。Spring中TypeConverterDelegate的convertIfNecessary方法用于类型转换:
// Value not of required type?
		if (pe != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {
			if (pe == null && descriptor != null) {
				if (JdkVersion.isAtLeastJava15()) {
					pe = descriptor.createPropertyEditor(this.targetObject);
				}
				else {
					Class editorClass = descriptor.getPropertyEditorClass();
					if (editorClass != null) {
						pe = (PropertyEditor) BeanUtils.instantiateClass(editorClass);
					}
				}
			}
			if (pe == null && requiredType != null) {
				// No custom editor -> check BeanWrapperImpl's default editors.
				pe = (PropertyEditor) this.propertyEditorRegistry.getDefaultEditor(requiredType);
				if (pe == null) {
					// No BeanWrapper default editor -> check standard JavaBean editors.
					pe = [color=red]PropertyEditorManager.findEditor(requiredType);[/color]
				}
			}
			convertedValue = convertValue(convertedValue, requiredType, pe, oldValue);
		}

当属性没有默认属性器、或者在自定义属性编辑器Map中没有对应的属性编辑器时,会调用PropertyEditorManager.findEditor(Class)方法。看看JDK源码中的实现:
public static synchronized PropertyEditor findEditor(Class<?> targetType) {
	initialize();
	Class editorClass = (Class)registry.get(targetType);
	if (editorClass != null) {
	    try {
		Object o = editorClass.newInstance();
        	return (PropertyEditor)o;
	    } catch (Exception ex) {
	 	System.err.println("Couldn't instantiate type editor \"" +
			editorClass.getName() + "\" : " + ex);
	    }
	}

	// Now try adding "Editor" to the class name.

	[color=red]String editorName = targetType.getName() + "Editor";
	try {
	    return (PropertyEditor) Introspector.instantiate(targetType, editorName);
	} catch (Exception ex) {
	   // Silently ignore any errors.
	}[/color]

	// Now try looking for <searchPath>.fooEditor
	editorName = targetType.getName();
   	while (editorName.indexOf('.') > 0) {
	    editorName = editorName.substring(editorName.indexOf('.')+1);
	}
	for (int i = 0; i < searchPath.length; i++) {
	    String name = searchPath[i] + "." + editorName + "Editor";
	    try {
	        return (PropertyEditor) Introspector.instantiate(targetType, name);
	    } catch (Exception ex) {
	       // Silently ignore any errors.
	    }
	}

	// We couldn't find a suitable Editor.
	return null;
    }


会自行在属性类型后加上Editor,然后试图加载响应的类并实例化。比如属性为Person,则会加载并实例化一个PersonEditor对象。

相关推荐

Global site tag (gtag.js) - Google Analytics