Exploration of groovy-covering invokemethod during the runtime of MOP 11
We will have been using the groovy hook language for a long time, that is, the "invokemethod" method and several other methods. We will implement the "invokemethod" method in a class, which is used to assign all or part of the methods of the class instance called during the runtime. We have discussed these in detail in the mop invokemethod and methodmissing method of groovy exploration.
Now, we have been deeply touched by the groovy metaclass language, and expandometaclass is also used everywhere. We all know that the flexibility of expandometaclass is not comparable to that of hook. Now that we can use expandometaclass to add methods to a class during runtime, can we also add hook methods during runtime?
We can answer, yes. Let's take a look at a simple example!
We still have such a simple class:
ClassFoo
{
DefFoo ()
{
'Foo'
}
}
We are now trying to add the "invokemethod" method during the runtime:
Foo. metaclass. invokemethod = {
String name, args1->
'Test'
}
Next, let's test the "invokemethod" method added during this runtime:
DefFoo =NewFoo ()
PrintlnFoo. Foo ()
PrintlnFoo.Test()
The running result is:
Test
Test
We can see that the "invokemethod" method we added during the runtime intercepts all the methods of the foo class instance.
Of course, if we want to intercept methods in the "invokemethod" method, the methods already exist in the foo class, such as "foo", and hand them over to the methods of the foo class. Then, we can implement the "invokemethod" method as follows:
Foo. metaclass. invokemethod = {
String name, args1->
DefM = Foo. metaclass. getmetamethod (name, args1)
DefResult
If(M)
Result = M. Invoke (delegate, args1)
Else
Result = 'test'
Result
}
Run the above test code and we will get the following results:
Foo
Test
Now, let's define several terms. The "invokemethod" method implemented by the class itself is called the "invokemethod" method of the object, the "invokemethod" method added by expandometaclass during runtime is called the "invokemethod" method of metaclass.
The problem is, if an object implements the "invokemethod" method of the object and the "invokemethod" method of metaclass, who should call it?
You will certainly say that this problem is very simple. We will not know if we will do a simple test. Now, let's take a look at this simple test.
First, we add the "invokemethod" method to the above Foo class:
ClassFoo
{
DefFoo ()
{
'Foo'
}
DefInvokemethod (string name, argS)
{
'Invoke'
}
}
At the same time, we also add this method during the runtime, and then perform the test:
Foo. metaclass. invokemethod = {
String name, args1->
DefM = Foo. metaclass. getmetamethod (name, args1)
DefResult
If(M)
Result = M. Invoke (delegate, args1)
Else
Result = 'test'
Result
}
DefFoo =NewFoo ()
PrintlnFoo. Foo ()
PrintlnFoo.Test()
The running result is:
Foo
Test
The result shows that the "invokemethod" method of metaclass overwrites the "invokemethod" method of the object. That is, if the "invokemethod" method of metaclass exists, the "invokemethod" method of metaclass is called first, regardless of whether the "invokemethod" method of the object exists.
Finally, we also define the "invokemethod" method of policyinterceptable. In fact, we have also been in touch with the mop invokemethod and methodmissing method of groovy exploration, that is, if a class implements the "yyinterceptable" interface, the "invokemethod" method of its class is the "invokemethod" method of yyinterceptable. As follows:
ClassFooImplementsYyinterceptable {
DefFoo ()
{
'Foo'
}
DefInvokemethod (string name, argS)
{
'Invoke'
}
}
Now, we need to know how to call the "invokemethod" method of policyinterceptable of an object and the "invokemethod" method of metaclass?
Or test the foo class that has implemented the "yyinterceptable" interface as follows:
Foo. metaclass. invokemethod = {
String name, args1->
DefM = Foo. metaclass. getmetamethod (name, args1)
DefResult
If(M)
Result = M. Invoke (delegate, args1)
Else
Result = 'test'
Result
}
DefFoo =NewFoo ()
PrintlnFoo. Foo ()
PrintlnFoo.Test()
The running result is:
Invoke
Invoke
The running results show that the "invokemethod" method of yyinterceptable takes precedence over the call of the "invokemethod" method of metaclass; or, if an object has the "invokemethod" method of yyinterceptable and the "invokemethod" method of metaclass, the system calls the "invokemethod" method of groovyinterceptable regardless of the "invokemethod" method of metaclass.
Finally, let's make a summary. If the class of an object implements the "yyinterceptable" interface, the system calls the "invokemethod" method of yyinterceptable. Otherwise, the system calls the "invokemethod" method of metaclass. If the object does not implement the "invokemethod" method of metaclass, the system calls the "invokemethod" method of the object.