aop的概念
aop:aspect-oriented programming(面向切面编程),维基百科的解释如下:aspect是一种新的模块化机制,用来描述分散在对象、类或者函数中的横切关注点,从关注点中分离出横切关注点是面向切面的程序设计的核心概念。分离关注点使解决特定领域问题的代码从业务逻辑中独立出来,业务逻辑的代码中不在含有针对特定领域问题的代码的调用,业务逻辑同特定领域问题的关系通过切面来封装、维护,这样原本分散在整个应用程序中的变动就可以很好地管理起来。从aop的角度,应用可以分为横切关注点和业务逻辑代码,实际开发中,这些横切关注点往往会直接嵌入到业务逻辑代码中,面向切面编程就是要解决把横切关注点与业务逻辑相分离
实现方式:
spring默认使用 jdk 动态代理作为aop的代理,缺陷是目标类的类必须实现接口,否则不能使用jdk动态代理。如果需要代理的是类而不是接口,那么spring会默认使用cglib代理,关于两者的区别:jdk动态代理是通过java的反射机制来实现的,目标类必须要实现接口,cglib是针对类来实现代理的,他的原理是动态的为指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
jdk动态代理
jdk动态代理是在程序运行过程中,根据目标类实现的接口来动态生成代理类的class文件,使用主要涉及两个类:
invocationhandler接口: 它提供了一个invoke(object obj,method method, object[] args)
方法供实现者提供相应的代理逻辑的实现。可以对实际的实现进行一些特殊的处理其中参数
object obj :被代理的目标类
method method: 需要执行的目标类的方法
object[] args :目标方法的参数
proxy类:提供一个方法newproxyinstance (classloader loader, class[] interfaces, invocationhandler h)
来获得动态代理类
示例代码:
1
2
3
|
public interface orderservice { public void createorder(); } |
1
2
3
4
5
6
7
|
public class orderserviceimpl implements orderservice { @override public void createorder() { system.out.println( "creating order" ); } } |
1
2
3
4
5
6
7
8
9
|
public class orderlogger { public void beforecreateorder(){ system.out.println( "before create order" ); } public void aftercreateorder(){ system.out.println( "after create order" ); } } |
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
|
package com.sl.aop; import java.lang.reflect.invocationhandler; import java.lang.reflect.method; import java.lang.reflect.proxy; public class serviceproxy implements invocationhandler { private object targetclass; private orderlogger orderlogger; public serviceproxy(object targetclass,orderlogger orderlogger) { this .targetclass = targetclass; this .orderlogger = orderlogger; } //获取代理 public object getdynamicproxy() { return proxy.newproxyinstance(targetclass.getclass().getclassloader(), //通过这个classloader生成代理对象 targetclass.getclass().getinterfaces(), //代理类已实现的接口 this ); //动态代理调用方法是关联的invocationhandler,最终通过此invocationhandler的invoke方法执行真正的方法 } //实现相应的代理逻辑 @override public object invoke(object proxy, method method, object[] args) throws throwable { this .orderlogger.beforecreateorder(); object result= method.invoke(targetclass, args); this .orderlogger.aftercreateorder(); return result; } } |
测试类:
1
2
3
4
5
6
7
8
9
10
11
12
|
package com.sl.aop; import org.junit.test; public class aoptest { @test public void testdynamicproxy() { orderserviceimpl serviceimpl = new orderserviceimpl(); orderlogger logger = new orderlogger(); orderservice service = (orderservice) new serviceproxy(serviceimpl, logger).getdynamicproxy(); service.createorder(); } } |
运行结果:
到这个其实还是有点困惑,proxy.newproxyinstance()
这个返回的是什么? invoke方法在哪里调用的?我们看一下jdk源码:看看dk动态代理的过程是什么样的:
根据源码内部的函数调用proxy.newproxyinstance()->proxy.getproxyclass0()->weakcache.get()
,先定位到
weakcache.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
|
public v get(k key, p parameter) { objects.requirenonnull(parameter); expungestaleentries(); object cachekey = cachekey.valueof(key, refqueue); // lazily install the 2nd level valuesmap for the particular cachekey concurrentmap<object, supplier<v>> valuesmap = map.get(cachekey); if (valuesmap == null ) { concurrentmap<object, supplier<v>> oldvaluesmap = map.putifabsent(cachekey, valuesmap = new concurrenthashmap<>()); if (oldvaluesmap != null ) { valuesmap = oldvaluesmap; } } // create subkey and retrieve the possible supplier<v> stored by that // subkey from valuesmap object subkey = objects.requirenonnull(subkeyfactory.apply(key, parameter)); supplier<v> supplier = valuesmap.get(subkey); factory factory = null ; while ( true ) { if (supplier != null ) { // supplier might be a factory or a cachevalue<v> instance v value = supplier.get(); if (value != null ) { return value; } } // else no supplier in cache // or a supplier that returned null (could be a cleared cachevalue // or a factory that wasn't successful in installing the cachevalue) // lazily construct a factory if (factory == null ) { factory = new factory(key, parameter, subkey, valuesmap); } if (supplier == null ) { supplier = valuesmap.putifabsent(subkey, factory); if (supplier == null ) { // successfully installed factory supplier = factory; } // else retry with winning supplier } else { if (valuesmap.replace(subkey, supplier, factory)) { // successfully replaced // cleared cacheentry / unsuccessful factory // with our factory supplier = factory; } else { // retry with current supplier supplier = valuesmap.get(subkey); } } } } |
可以看到函数return value; 而 v value = supplier.get();
继续往下读可以发现 supper=factory,实际上是一个factory对象,那么继续查看factory.get()
方法
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
|
public synchronized v get() { // serialize access // re-check supplier<v> supplier = valuesmap.get(subkey); if (supplier != this ) { // something changed while we were waiting: // might be that we were replaced by a cachevalue // or were removed because of failure -> // return null to signal weakcache.get() to retry // the loop return null ; } // else still us (supplier == this) // create new value v value = null ; try { value = objects.requirenonnull(valuefactory.apply(key, parameter)); } finally { if (value == null ) { // remove us on failure valuesmap.remove(subkey, this ); } } // the only path to reach here is with non-null value assert value != null ; // wrap value with cachevalue (weakreference) cachevalue<v> cachevalue = new cachevalue<>(value); // try replacing us with cachevalue (this should always succeed) if (valuesmap.replace(subkey, this , cachevalue)) { // put also in reversemap reversemap.put(cachevalue, boolean . true ); } else { throw new assertionerror( "should not reach here" ); } // successfully replaced us with new cachevalue -> return the value // wrapped by it return value; } |
return value;那么直接查看赋值语句:value = objects.requirenonnull(valuefactory.apply(key, parameter));
valuefactory又什么鬼?
1
2
3
4
5
6
7
|
public weakcache(bifunction<k, p, ?> subkeyfactory, bifunction<k, p, v> valuefactory) { this .subkeyfactory = objects.requirenonnull(subkeyfactory); this .valuefactory = objects.requirenonnull(valuefactory); } private static final weakcache<classloader, class <?>[], class <?>> proxyclasscache = new weakcache<>( new keyfactory(), new proxyclassfactory()); |
可以知道valuefactory是proxyclassfactory类型对象,直接查看proxyclassfactory. apply()
方法
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
|
public class <?> apply(classloader loader, class <?>[] interfaces) { map< class <?>, boolean > interfaceset = new identityhashmap<>(interfaces.length); for ( class <?> intf : interfaces) { /* * verify that the class loader resolves the name of this * interface to the same class object. */ class<?> interfaceclass = null; try { interfaceclass = class.forname(intf.getname(), false, loader); } catch (classnotfoundexception e) { } if (interfaceclass != intf) { throw new illegalargumentexception( intf + " is not visible from class loader"); } /* * verify that the class object actually represents an * interface. */ if (!interfaceclass.isinterface()) { throw new illegalargumentexception( interfaceclass.getname() + " is not an interface"); } /* * verify that this interface is not a duplicate. */ if (interfaceset.put(interfaceclass, boolean.true) != null) { throw new illegalargumentexception( "repeated interface: " + interfaceclass.getname()); } } string proxypkg = null; // package to define proxy class in int accessflags = modifier.public | modifier.final; /* * record the package of a non-public proxy interface so that the * proxy class will be defined in the same package. verify that * all non-public proxy interfaces are in the same package. */ for (class<?> intf : interfaces) { int flags = intf.getmodifiers(); if (!modifier.ispublic(flags)) { accessflags = modifier.final; string name = intf.getname(); int n = name.lastindexof('.'); string pkg = ((n == -1) ? "" : name.substring(0, n + 1)); if (proxypkg == null) { proxypkg = pkg; } else if (!pkg.equals(proxypkg)) { throw new illegalargumentexception( "non-public interfaces from different packages"); } } } if (proxypkg == null) { // if no non-public proxy interfaces, use com.sun.proxy package proxypkg = reflectutil.proxy_package + "."; } /* * choose a name for the proxy class to generate. */ long num = nextuniquenumber.getandincrement(); string proxyname = proxypkg + proxyclassnameprefix + num; /* * generate the specified proxy class. */ byte[] proxyclassfile = proxygenerator.generateproxyclass( proxyname, interfaces, accessflags); try { return defineclass0(loader, proxyname, proxyclassfile, 0, proxyclassfile.length); } catch (classformaterror e) { /* * a classformaterror here means that (barring bugs in the * proxy class generation code) there was some other * invalid aspect of the arguments supplied to the proxy * class creation (such as virtual machine limitations * exceeded). */ throw new illegalargumentexception(e.tostring()); } } } |
直接画重点:
1
2
3
4
|
byte [] proxyclassfile = proxygenerator.generateproxyclass( proxyname, interfaces, accessflags); return defineclass0(loader, proxyname, proxyclassfile, 0 , proxyclassfile.length); |
调用proxygenerator.generateproxyclass
最终动态生成一个代理类,但是似乎并未找到何处调用了invoke方法;参考csdn: http://www.zzvips.com/article/120039.html 这篇文章,尝试将这个动态生成的二进制字节码输出到本地,并反编译出来一看究竟,测试代码如下:
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
|
public class aoptest { @test public void testdynamicproxy() { orderserviceimpl serviceimpl = new orderserviceimpl(); orderlogger logger = new orderlogger(); orderservice service = (orderservice) new serviceproxy(serviceimpl, logger).getdynamicproxy(); service.createorder(); //输出动态代理类字节码 createproxyclassfile(); } private static void createproxyclassfile(){ string name = "proxyobject" ; byte [] data = proxygenerator.generateproxyclass(name, new class []{orderservice. class }); fileoutputstream out = null ; try { out = new fileoutputstream(name+ ".class" ); system.out.println(( new file( "hello" )).getabsolutepath()); out.write(data); } catch (filenotfoundexception e) { e.printstacktrace(); } catch (ioexception e) { e.printstacktrace(); } finally { if ( null !=out) try { out.close(); } catch (ioexception e) { e.printstacktrace(); } } } } |
使用java decompiler工具将这个二进制class文件反编译查看:
具体动态代理类proxyobject.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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
import com.sl.aop.orderservice; import java.lang.reflect.invocationhandler; import java.lang.reflect.method; import java.lang.reflect.proxy; import java.lang.reflect.undeclaredthrowableexception; public final class proxyobject extends proxy implements orderservice { private static method m1; private static method m2; private static method m3; private static method m0; public proxyobject(invocationhandler paraminvocationhandler) { super (paraminvocationhandler); } public final boolean equals(object paramobject) { try { return (( boolean ) this .h.invoke( this , m1, new object[] { paramobject })).booleanvalue(); } catch (error|runtimeexception localerror) { throw localerror; } catch (throwable localthrowable) { throw new undeclaredthrowableexception(localthrowable); } } public final string tostring() { try { return (string) this .h.invoke( this , m2, null ); } catch (error|runtimeexception localerror) { throw localerror; } catch (throwable localthrowable) { throw new undeclaredthrowableexception(localthrowable); } } public final void createorder() { try { this .h.invoke( this , m3, null ); return ; } catch (error|runtimeexception localerror) { throw localerror; } catch (throwable localthrowable) { throw new undeclaredthrowableexception(localthrowable); } } public final int hashcode() { try { return ((integer) this .h.invoke( this , m0, null )).intvalue(); } catch (error|runtimeexception localerror) { throw localerror; } catch (throwable localthrowable) { throw new undeclaredthrowableexception(localthrowable); } } static { try { m1 = class .forname( "java.lang.object" ).getmethod( "equals" , new class [] { class .forname( "java.lang.object" ) }); m2 = class .forname( "java.lang.object" ).getmethod( "tostring" , new class [ 0 ]); m3 = class .forname( "com.sl.aop.orderservice" ).getmethod( "createorder" , new class [ 0 ]); m0 = class .forname( "java.lang.object" ).getmethod( "hashcode" , new class [ 0 ]); return ; } catch (nosuchmethodexception localnosuchmethodexception) { throw new nosuchmethoderror(localnosuchmethodexception.getmessage()); } catch (classnotfoundexception localclassnotfoundexception) { throw new noclassdeffounderror(localclassnotfoundexception.getmessage()); } } |
终于看到关于invoke的部分了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public final void createorder() { try { this .h.invoke( this , m3, null ); return ; } catch (error|runtimeexception localerror) { throw localerror; } catch (throwable localthrowable) { throw new undeclaredthrowableexception(localthrowable); } } |
实际上动态代理类继承自proxy,并且实现了目标类继承的接口,在createorder方法中调用了invoke方法,实现了切面逻辑的植入,这里也回答了一个问题,为什么jdk动态代理的目标类必须是实现接口的,因为代理类其实是针对接口代理,而不是针对类来代理的,动态代理类自己继承自proxy,java也不允许多重继承。动态代理类和目标类其实是各自实现了接口,代理类通过invocationhandler.invoke实现对目标类方法的调用。
cglib动态代理
cglib代理是通过使用一个字节码处理框架asm,来转换字节码并生成新的类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,实现织如如横切逻辑 ,效率上比使用反射技术的jdk动态代理要高,但是由于cglib的原理是动态为目标类生成子类代理类,所以不能为声明为final的方法进行代理。其使用主要涉及两个类:
methodinterceptor接口:该接口提供一个方法intercept(object arg0, method arg1, object[] arg2, methodproxy arg3)
主要用于拦截目标类方法的调用
object arg0, :被代理的目标类
method arg1, 委托方法
object[] arg2, 方法参数
methodproxy arg3 :代理方法的methodproxy对象
enhancer类:用于创建代理类
示例:
实现methodinterceptor接口,代理类在调用方法时,cglib会回调methodinterceptor接口intercept方法,从而织入切面逻辑。
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
|
package com.sl.aop; import java.lang.reflect.method; import org.springframework.cglib.proxy.enhancer; import org.springframework.cglib.proxy.methodinterceptor; import org.springframework.cglib.proxy.methodproxy; public class cglibserviceproxy implements methodinterceptor { private object targetclass; private orderlogger orderlogger; public cglibserviceproxy(object targetclass,orderlogger orderlogger) { this .targetclass = targetclass; this .orderlogger = orderlogger; } /** * 创建代理对象 * */ public object getinstance() { enhancer enhancer = new enhancer(); //设置目标类(需要被代理的类) enhancer.setsuperclass( this .targetclass.getclass()); // 回调方法 enhancer.setcallback( this ); // 创建代理对象 return enhancer.create(); } /** * 拦截所有目标类方法的调用 * */ @override public object intercept(object arg0, method arg1, object[] arg2, methodproxy arg3) throws throwable { orderlogger.beforecreateorder(); object o1 = arg3.invokesuper(arg0, arg2); orderlogger.aftercreateorder(); return o1; } } |
测试方法:
1
2
3
4
5
6
7
8
9
|
public void testdynamicproxy() { system.setproperty(debuggingclasswriter.debug_location_property, "d:\\class" ); orderserviceimpl serviceimpl = new orderserviceimpl(); orderlogger logger = new orderlogger(); cglibserviceproxy proxy = new cglibserviceproxy(serviceimpl,logger); //通过生成子类的方式创建代理类 orderserviceimpl proxyimp = (orderserviceimpl)proxy.getinstance(); proxyimp.createorder(); } |
结果:
system.setproperty(debuggingclasswriter.debug_location_property, "d:\\class");
将cglib动态代理类输出到指定目录,反编译查看一下代理类真面目:
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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
|
package com.sl.aop; import com.sl.aop.orderserviceimpl; import java.lang.reflect.method; import org.springframework.cglib.core.reflectutils; import org.springframework.cglib.core.signature; import org.springframework.cglib.proxy.callback; import org.springframework.cglib.proxy.factory; import org.springframework.cglib.proxy.methodinterceptor; import org.springframework.cglib.proxy.methodproxy; public class orderserviceimpl$$enhancerbycglib$$17779aa4 extends orderserviceimpl implements factory { private boolean cglib$bound; public static object cglib$factory_data; private static final threadlocal cglib$thread_callbacks; private static final callback[] cglib$static_callbacks; private methodinterceptor cglib$callback_0; private static object cglib$callback_filter; private static final method cglib$createorder$ 0 $method; private static final methodproxy cglib$createorder$ 0 $proxy; private static final object[] cglib$emptyargs; private static final method cglib$equals$ 1 $method; private static final methodproxy cglib$equals$ 1 $proxy; private static final method cglib$tostring$ 2 $method; private static final methodproxy cglib$tostring$ 2 $proxy; private static final method cglib$hashcode$ 3 $method; private static final methodproxy cglib$hashcode$ 3 $proxy; private static final method cglib$clone$ 4 $method; private static final methodproxy cglib$clone$ 4 $proxy; static void cglib$statichook1() { cglib$thread_callbacks = new threadlocal(); cglib$emptyargs = new object[ 0 ]; class var0 = class .forname( "com.sl.aop.orderserviceimpl$$enhancerbycglib$$17779aa4" ); class var1; method[] var10000 = reflectutils.findmethods( new string[]{ "equals" , "(ljava/lang/object;)z" , "tostring" , "()ljava/lang/string;" , "hashcode" , "()i" , "clone" , "()ljava/lang/object;" }, (var1 = class .forname( "java.lang.object" )).getdeclaredmethods()); cglib$equals$ 1 $method = var10000[ 0 ]; cglib$equals$ 1 $proxy = methodproxy.create(var1, var0, "(ljava/lang/object;)z" , "equals" , "cglib$equals$1" ); cglib$tostring$ 2 $method = var10000[ 1 ]; cglib$tostring$ 2 $proxy = methodproxy.create(var1, var0, "()ljava/lang/string;" , "tostring" , "cglib$tostring$2" ); cglib$hashcode$ 3 $method = var10000[ 2 ]; cglib$hashcode$ 3 $proxy = methodproxy.create(var1, var0, "()i" , "hashcode" , "cglib$hashcode$3" ); cglib$clone$ 4 $method = var10000[ 3 ]; cglib$clone$ 4 $proxy = methodproxy.create(var1, var0, "()ljava/lang/object;" , "clone" , "cglib$clone$4" ); cglib$createorder$ 0 $method = reflectutils.findmethods( new string[]{ "createorder" , "()v" }, (var1 = class .forname( "com.sl.aop.orderserviceimpl" )).getdeclaredmethods())[ 0 ]; cglib$createorder$ 0 $proxy = methodproxy.create(var1, var0, "()v" , "createorder" , "cglib$createorder$0" ); } final void cglib$createorder$ 0 () { super .createorder(); } public final void createorder() { methodinterceptor var10000 = this .cglib$callback_0; if ( this .cglib$callback_0 == null ) { cglib$bind_callbacks( this ); var10000 = this .cglib$callback_0; } if (var10000 != null ) { var10000.intercept( this , cglib$createorder$ 0 $method, cglib$emptyargs, cglib$createorder$ 0 $proxy); } else { super .createorder(); } } final boolean cglib$equals$ 1 (object var1) { return super .equals(var1); } public final boolean equals(object var1) { methodinterceptor var10000 = this .cglib$callback_0; if ( this .cglib$callback_0 == null ) { cglib$bind_callbacks( this ); var10000 = this .cglib$callback_0; } if (var10000 != null ) { object var2 = var10000.intercept( this , cglib$equals$ 1 $method, new object[]{var1}, cglib$equals$ 1 $proxy); return var2 == null ? false :(( boolean )var2).booleanvalue(); } else { return super .equals(var1); } } final string cglib$tostring$ 2 () { return super .tostring(); } public final string tostring() { methodinterceptor var10000 = this .cglib$callback_0; if ( this .cglib$callback_0 == null ) { cglib$bind_callbacks( this ); var10000 = this .cglib$callback_0; } return var10000 != null ?(string)var10000.intercept( this , cglib$tostring$ 2 $method, cglib$emptyargs, cglib$tostring$ 2 $proxy): super .tostring(); } final int cglib$hashcode$ 3 () { return super .hashcode(); } public final int hashcode() { methodinterceptor var10000 = this .cglib$callback_0; if ( this .cglib$callback_0 == null ) { cglib$bind_callbacks( this ); var10000 = this .cglib$callback_0; } if (var10000 != null ) { object var1 = var10000.intercept( this , cglib$hashcode$ 3 $method, cglib$emptyargs, cglib$hashcode$ 3 $proxy); return var1 == null ? 0 :((number)var1).intvalue(); } else { return super .hashcode(); } } final object cglib$clone$ 4 () throws clonenotsupportedexception { return super .clone(); } protected final object clone() throws clonenotsupportedexception { methodinterceptor var10000 = this .cglib$callback_0; if ( this .cglib$callback_0 == null ) { cglib$bind_callbacks( this ); var10000 = this .cglib$callback_0; } return var10000 != null ?var10000.intercept( this , cglib$clone$ 4 $method, cglib$emptyargs, cglib$clone$ 4 $proxy): super .clone(); } public static methodproxy cglib$findmethodproxy(signature var0) { string var10000 = var0.tostring(); switch (var10000.hashcode()) { case - 2138148221 : if (var10000.equals( "createorder()v" )) { return cglib$createorder$ 0 $proxy; } break ; case - 508378822 : if (var10000.equals( "clone()ljava/lang/object;" )) { return cglib$clone$ 4 $proxy; } break ; case 1826985398 : if (var10000.equals( "equals(ljava/lang/object;)z" )) { return cglib$equals$ 1 $proxy; } break ; case 1913648695 : if (var10000.equals( "tostring()ljava/lang/string;" )) { return cglib$tostring$ 2 $proxy; } break ; case 1984935277 : if (var10000.equals( "hashcode()i" )) { return cglib$hashcode$ 3 $proxy; } } return null ; } public orderserviceimpl$$enhancerbycglib$$17779aa4() { cglib$bind_callbacks( this ); } public static void cglib$set_thread_callbacks(callback[] var0) { cglib$thread_callbacks.set(var0); } public static void cglib$set_static_callbacks(callback[] var0) { cglib$static_callbacks = var0; } private static final void cglib$bind_callbacks(object var0) { orderserviceimpl$$enhancerbycglib$$17779aa4 var1 = (orderserviceimpl$$enhancerbycglib$$17779aa4)var0; if (!var1.cglib$bound) { var1.cglib$bound = true ; object var10000 = cglib$thread_callbacks.get(); if (var10000 == null ) { var10000 = cglib$static_callbacks; if (cglib$static_callbacks == null ) { return ; } } var1.cglib$callback_0 = (methodinterceptor)((callback[])var10000)[ 0 ]; } } public object newinstance(callback[] var1) { cglib$set_thread_callbacks(var1); orderserviceimpl$$enhancerbycglib$$17779aa4 var10000 = new orderserviceimpl$$enhancerbycglib$$17779aa4(); cglib$set_thread_callbacks((callback[]) null ); return var10000; } public object newinstance(callback var1) { cglib$set_thread_callbacks( new callback[]{var1}); orderserviceimpl$$enhancerbycglib$$17779aa4 var10000 = new orderserviceimpl$$enhancerbycglib$$17779aa4(); cglib$set_thread_callbacks((callback[]) null ); return var10000; } public object newinstance( class [] var1, object[] var2, callback[] var3) { cglib$set_thread_callbacks(var3); orderserviceimpl$$enhancerbycglib$$17779aa4 var10000 = new orderserviceimpl$$enhancerbycglib$$17779aa4; switch (var1.length) { case 0 : var10000.<init>(); cglib$set_thread_callbacks((callback[]) null ); return var10000; default : throw new illegalargumentexception( "constructor not found" ); } } public callback getcallback( int var1) { cglib$bind_callbacks( this ); methodinterceptor var10000; switch (var1) { case 0 : var10000 = this .cglib$callback_0; break ; default : var10000 = null ; } return var10000; } public void setcallback( int var1, callback var2) { switch (var1) { case 0 : this .cglib$callback_0 = (methodinterceptor)var2; default : } } public callback[] getcallbacks() { cglib$bind_callbacks( this ); return new callback[]{ this .cglib$callback_0}; } public void setcallbacks(callback[] var1) { this .cglib$callback_0 = (methodinterceptor)var1[ 0 ]; } static { cglib$statichook1(); } } |
上面的代码可以看到代理类orderserviceimpl$$enhancerbycglib$$17779aa4 继承目标类orderserviceimpl并且实现了接口factory,代理类中关于createorder生成了两个方法cglib$createorder$0和createorder:
cglib$createorder$0方法内部直接调用目标类的supper.createorder
createorder方法内部首先盘点否实现了methodinterceptor接口的callback,如果存在则调用methodinterceptor接口拦截方法intercept,根据前面的实现intercept方法内部实现了对目标方法的调用object o1 = arg3.invokesuper(arg0, arg2)
,invokesuper内部实际上是直接调用的代理类的cglib$createorder$0()
方法,最终调用了目标类createorder。
两种代理对比
jdk动态代理:
代理类与委托类实现同一接口,主要是通过代理类实现invocationhandler并重写invoke方法来进行动态代理的,在invoke方法中将对方法进行增强处理 优点:不需要硬编码接口,代码复用率高,缺点:只能够代理实现了接口的委托类
cglib动态代理:
代理类将委托类作为自己的父类并为其中的非final委托方法创建两个方法,一个是与委托方法签名相同的方法,它在方法中会通过super调用委托方法;另一个是代理类独有的方法。在代理方法中,它会判断是否存在实现了methodinterceptor接口的对象,若存在则将调用intercept方法对委托方法进行代理 优点:可以在运行时对类或者是接口进行增强操作,且委托类无需实现接口,缺点:不能对final类以及final方法进行代理
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。
原文链接:http://www.cnblogs.com/ashleyboy/p/9027072.html