这意味着您只能在同一线程中调用通过category类添加的方法。考虑以下示例:
class StringUtils {
static String transform(String source) {
return source.toUpperCase().reverse().substring(0, source.length() / 2 as int)
}
}
use (StringUtils) {
println "Lorem ipsum".transform()
}
在本例中,我们添加
String.transform()
方法通过类别。运行此示例将生成以下输出:
MUSPI
在本例中,我们在
main
线程,我们已经调用
一串转换()
中的方法
主要的
还有螺纹。
现在让我们稍微更改一下这个示例,然后调用
一串转换()
方法外部
主要的
通过在新启动的线程中调用线程:
class StringUtils {
static String transform(String source) {
return source.toUpperCase().reverse().substring(0, source.length() / 2 as int)
}
}
use (StringUtils) {
Thread.start {
println "Lorem ipsum".transform()
}
}
我们使用了
StringUtil
中的类别类
主要的
线程,我们从
Thread-1
线让我们看看运行它时会发生什么:
Exception in thread "Thread-1" groovy.lang.MissingMethodException: No signature of method: java.lang.String.transform() is applicable for argument types: () values: []
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:58)
at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:49)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
at script$_run_closure1$_closure2.doCall(script.groovy:9)
at script$_run_closure1$_closure2.doCall(script.groovy)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
at groovy.lang.Closure.call(Closure.java:414)
at groovy.lang.Closure.call(Closure.java:408)
at groovy.lang.Closure.run(Closure.java:495)
at java.lang.Thread.run(Thread.java:748)
引发异常,因为
一串转换()
的范围中不存在
螺纹-1
线程-它仅存在于
主要的
线
但是让我们假设我们必须在
螺纹-1
线程范围。我们可以通过定义
use(StringUtils){}
内部
螺纹-1
块,例如。
class StringUtils {
static String transform(String source) {
return source.toUpperCase().reverse().substring(0, source.length() / 2 as int)
}
}
Thread.start {
use(StringUtils) {
println "Lorem ipsum".transform()
}
}
现在一切正常-类别使用块在内部定义
螺纹-1
我们打电话
一串转换()
方法。运行此示例会向控制台生成预期的输出:
MUSPI公司
这是什么
类别使用仅限于当前线程
实践中的方法。
但是如何调用此方法?
当我们打电话时:
"Lorem ipsum".transform()
从上面的示例中,下面的Groovy方法处理
transform()
方法:
groovy.lang.MetaClassImpl.invokeMethod(Class sender, Object object, String methodName, Object[] originalArguments, boolean isCallToSuper, boolean fromInsideClass)
您可以在第1044行(Groovy 2.4.12)找到它。
转换()
类中不存在方法
String
因此Groovy必须在其他地方找到它的实现。在这种情况下,方法见第1055行:
MetaMethod method = null;
if (CLOSURE_CALL_METHOD.equals(methodName) && object instanceof GeneratedClosure) {
method = getMethodWithCaching(sender, "doCall", arguments, isCallToSuper);
}
该方法最重要的部分是第1283行:
if (!isCallToSuper && GroovyCategorySupport.hasCategoryInCurrentThread()) {
return getMethodWithoutCaching(sender, methodName, MetaClassHelper.convertToTypeArray(arguments), isCallToSuper);
} else {
....
}
GroovyCategorySupport.hasCategoryInCurrentThread()
检查类别是否在当前线程中使用(
ThreadLocal
在这种情况下使用)。
如果您跟踪接下来发生的事情,您将获得
MetaClassImpl
第690行,其中
getMethods(Class sender, String name, boolean isCallToSuper)
位于。在第706行中,此方法调用:
List used = GroovyCategorySupport.getCategoryMethods(name);
这是在category类中按名称查找方法的最后一部分。稍后,它会检查该方法是否是静态的,以及是否需要具有有效类型的参数(
一串
在这种情况下)。