This article mainly introduces relevant information for in-depth understanding of Java dynamic proxy. Friends who need it can refer to it
If you want to understand Java dynamic proxy, you must first understand what a proxy is and be familiar with design patterns. Friends of must know that among the 23 design patterns summarized by Gof, there is a object structural pattern called Proxy. The proxy in dynamic proxy refers to this design pattern.
In my opinion, the so-called agency mode is the same thing as the "decoration mode" among the 23 design patterns. Among the 23 design patterns, they are regarded as two patterns. There are also some articles on the Internet about the similarities and differences of these two patterns. From the details, it is indeed possible to distinguish the two patterns artificially. However, after abstracting to a certain level, I think these two patterns are not the same. The patterns are exactly the same. Therefore, if you learn the proxy mode, you will also master the decoration mode.
Agent mode
The proxy mode is simply to wrap an object. The object generated after packaging has the same method list as the original object, but each Methods can be wrapped.
staticAgent
Let’s look at a piece of code first:
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 |
|
This code first defines a SubjectInterface, which has two methods.
Then the SubjectImpl class is defined to implement the Subject interface and implements two of its methods. There is definitely no problem here.
Now define another SubjuectImplProxy class and also implement the Subject interface. The function of this SubjectImplProxy class is to wrap an instance of the SubjectImpl class. It defines a variable target internally to save an instance of SubjectImpl. SubjectImplProxy also implements the two methods specified by the interface, and in its implementation version, it calls the implementation of SubjectImpl, but adds its own processing logic.
I believe this code is not difficult to understand. It achieves the function of adding a prefix to the output content by packaging SubjectImpl. This proxy method is called static proxy.
Dynamic proxy
From the above demonstration, it is not difficult to see the shortcomings of static proxy: we use the same packaging for the two methods of SubjectImpl, but But you have to write the same packaging logic twice in SubjectImplProxy, and if the Subject interface adds new methods in the future, SubjectImplProxy must also add new implementations, although SubjectImplProxy may wrap all methods the same.
Below I change the static proxy in the above example to a dynamic proxy. Let’s take a look at the difference:
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 |
|
If you only look at the main method, only the second one The line is different from the previous static proxy. It also generates a subjectProxy proxy object, but the generated code is different. The static proxy directly new an instance of SubjectImplProxy, while the dynamic proxy calls the java.lang.reflect.Proxy.newProxyInstance() method. Let’s take a look at the source code of this method:
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 |
|
The above Class cl = getProxyClass(loader, interfaces); The getProxyClass method called:
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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
|
Go here, We have parsed the java source code of the dynamic proxy, and now the idea is very clear:
Proxy.newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h) method is simply executed The following operations are performed:
1. Generate a bytecode of a proxy class that implements all the interfaces in the parameter interfaces and inherits Proxy, and then uses the classLoader in the parameter to load the proxy class.
2. Use the constructor Proxy(InvocationHandler h) of the parent class of the proxy class to create an instance of the proxy class and pass in the subclass of our custom InvocationHandler.
3. Return this proxy class instance, because the proxy class we constructed implements all the interfaces in interfaces (that is, the subject.getClass().getInterfaces() passed in in our program), so the returned The proxy class can be cast to the Subject type to call the methods defined in the interface.
Now we know that the subjectProxy returned by Proxy.newProxyInstance() can be successfully converted into a Subject type to call the method defined in the interface. So how is the proxy class instance processed after the method is called? This requires taking a look at the source code of the proxy class. But the proxy class is loaded by dynamically generated bytecode by the program. How to look at the source code? It doesn't matter, you can add System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true") to the main method, so that the generated proxy class Class file will be saved on the local disk, and then returned Compile to get the source code of the proxy class:
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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
|
我们可以看到代理类内部实现比较简单,在调用每个代理类每个方法的时候,都用反射去调h的invoke方法(也就是我们自定义的InvocationHandler的子类中重写的invoke方法),用参数传递了代理类实例、接口方法、调用参数列表,这样我们在重写的invoke方法中就可以实现对所有方法的统一包装了。
总结
动态代理相对于静态代理在使用上的优点主要是能够对一个对象的所有方法进行统一包装,而且后期被代理的类添加方法的时候动态代理类不需要改动。
缺点是要求被代理的类必须实现了接口,因为动态代理类在实现的时候继承了Proxy类,java不支持多继承,因此动态代理类只能根据接口来定义方法。
最后动态代理之所以叫做动态代理是因为java在实现动态代理的时候,动态代理类是在运行时动态生成和加载的,相对的,静态代理类和其他普通类一下,在类加载阶段就加载了。
The above is the detailed content of In-depth understanding of Java dynamic proxy sample code. For more information, please follow other related articles on the PHP Chinese website!