-
Notifications
You must be signed in to change notification settings - Fork 1
/
DynamicLoggingProxy.java
81 lines (68 loc) · 2.03 KB
/
DynamicLoggingProxy.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*
Dynamic Proxy for logging
Example: build a dynamic proxy which takes an existing object of type Person
and counts the number inside of Person that have been called
*/
package structural.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
interface Human
{
void walk();
void talk();
}
class Person implements Human
{
@Override
public void walk() {
System.out.println("I am walking");
}
@Override
public void talk() {
System.out.println("I am talking");
}
}
class LoggingHandler implements InvocationHandler
{
private final Object target; // Need reference to an object
private Map<String, Integer> calls = new HashMap<>(); // map names of methods to how many times they've been called
public LoggingHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName();
// Here we intercept the toString function and change its output
if (name.contains("toString"))
{
return calls.toString();
}
calls.merge(name, 1, Integer::sum); // merge explanation: https://www.geeksforgeeks.org/hashmap-mergekey-value-bifunction-method-in-java-with-examples/
return method.invoke(target, args); // reflection API
}
}
class DynamicProxyDemo
{
// Utility function
@SuppressWarnings("unchecked")
public static <T> T withLogging(T target, Class<T> itf)
{
return (T) Proxy.newProxyInstance(
itf.getClassLoader(),
new Class<?>[] { itf },
new LoggingHandler(target)
);
}
public static void main(String[] args)
{
Person person = new Person();
Human logged = withLogging(person, Human.class);
logged.talk();
logged.walk();
logged.walk();
System.out.println(logged);
}
}