问题
For example, I have thousands of method like:
AA() {
...
}
BB() {
...
}
CC() {
...
}
etc ...
Now I want to call a method printCurrentMethodName() on the beginning of each method. That means,
AA() {
printCurrentMethodName();
...
}
BB() {
printCurrentMethodName();
...
}
CC() {
printCurrentMethodName();
...
}
etc ...
Including printCurrentMethodName() on the start of thousands of method is time consuming.
Is there any way that I can call printCurrentMethodName() on the beginning of each methods without repeating it in those thousands of method?
(I can't use something like @Before or @BeforeMethod annotation, because it will call printCurrentMethodName() before entering AA() and so it will not print the method name as expected)
回答1:
If you only want to print the names of the test methods then you could create a JUnit rule that is similar to the TestName rule
public class PrintTestName extends TestWatcher {
@Override
protected void starting(Description d) {
System.out.println(d.getMethodName());
}
}
and use it in your test
public class YourTest {
@Rule
public final PrintTestName printTestName = new PrintTestName();
@Test
public AA() {
...
}
...
回答2:
You can use java.lang.reflect.InvocationHandler
for this purpose.
Before any of the methods inside your class is called (AA
,BB
,CC
etc.) the invoke
method of your InvocationHandler
is called. Inside the invoke
method you have access to the actual method that was called and you can add additional logic, like printing the name the called method, to be executed before or after the actual method is called.
Code example:
public class PrintClassName {
public static void main(String[] a) {
Service srv = (Service) Proxy.newProxyInstance(
PrintClassName.class.getClassLoader(),
new Class<?>[]{Service.class},
new PrintingMethodNameHandler(new ServiceImpl())
);
srv.doNothing();
}
}
interface Service {
void doNothing();
}
class ServiceImpl implements Service {
public void doNothing() { }
}
class PrintingMethodNameHandler implements InvocationHandler {
private Service service;
public PrintingMethodNameHandler(final Service service) {
this.service = service;
}
@Override
public Object invoke(final Object proxy, final Method method,
final Object[] args) throws Throwable {
System.out.println(method.getName());
return method.invoke(service, args);
}
}
回答3:
You could use a regex to insert this call on every function.
Replace (\w+\(\w*\)\s*\{)
with $1\nprintCurrentMethodName();
回答4:
How about using AspectJ annotations.
For ex-
Common AspectJ annotations : 1.@Before – Run before the method execution
2.@After – Run after the method returned a result
3.@AfterReturning – Run after the method returned a result, intercept the returned result as well.
4.@AfterThrowing – Run after the method throws an exception
5.@Around – Run around the method execution, combine all three advices above.
This may solve your problem . You can use this to call a method when it is returned,
You may follow this tutorial.
回答5:
It is simple, Put this line in your method.
System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName());
来源:https://stackoverflow.com/questions/31239200/how-to-call-a-method-without-repeat-from-other-methods-in-java