java.lang.reflect.Proxy,
Proxy 提供用于创建动态代理类和实例的静态方法. 只能针对接口创建代理
newProxyInstance()
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序
(详见api文档)
java.lang.reflect.InvocationHandler,
InvocationHandler 是代理实例的调用处理程序 实现的接口。
invoke()
在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。
动态代理的使用代码示例如下:
1 public static void main(String[] args) {
2
3 InvocationHandler ih = new InvocationHandler() {
4
5 public Object invoke(Object proxy, Method method, Object[] args)
6 throws Throwable {
7 // 拦截方法处理
8 return null;
9 }
10
11 };
12
13 Class<?>[] interfaces = new Class<?>[] {BankAccount.class};
14
15 BankAccount bankAccount = (BankAccount) Proxy.newProxyInstance(ProxyTest
16 .class.getClassLoader(), interfaces, ih);
17 }
18
下面是动态代理生成的代码对应(通过反编译工具对字节码进行处理)
接口代码:
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> 1 public interface BankAccount {
2
3 boolean deposit(BigDecimal money);
4
5 boolean withdraw(BigDecimal money);
6
7 String getName();
8
9 String getId();
10 }
11
动态代理生成的字节码(反编译后的Java代码)
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> 1 public final class BankAccount$1 extends Proxy implements BankAccount {
2 private static Method m6; // getId
3 private static Method m4; // withdraw
4 private static Method m5; // getName
5 private static Method m2; // toString
6 private static Method m0; // hashCode
7 private static Method m3; // deposit
8 private static Method m1; // equals
9
10 public BankAccount$1(InvocationHandler ih) {
11 super(ih);
12 }
13
14 public final String getId() {
15 try {
16 return (String) this.h.invoke(this, m6, null);
17 } catch (RuntimeException e) {
18 throw e;
19 } catch (Throwable t) {
20 throw new UndeclaredThrowableException(t);
21 }
22 }
23
24 public final boolean withdraw(BigDecimal paramBigDecimal) {
25 try {
26 return ((Boolean) this.h.invoke(this, m4,
27 new Object[] { paramBigDecimal })).booleanValue();
28 } catch (RuntimeException e) {
29 throw e;
30 } catch (Throwable t) {
31 throw new UndeclaredThrowableException(t);
32 }
33 }
34
35 public final String getName() {
36 try {
37 return (String) this.h.invoke(this, m5, null);
38 } catch (RuntimeException e) {
39 throw e;
40 } catch (Throwable t) {
41 throw new UndeclaredThrowableException(t);
42 }
43 }
44
45 public final String toString() {
46 try {
47 return (String) this.h.invoke(this, m2, null);
48 } catch (RuntimeException localRuntimeException) {
49 throw localRuntimeException;
50 } catch (Throwable t) {
51 throw new UndeclaredThrowableException(t);
52 }
53 }
54
55 public final int hashCode() {
56 try {
57 return ((Integer) this.h.invoke(this, m0, null)).intValue();
58 } catch (RuntimeException e) {
59 throw e;
60 } catch (Throwable t) {
61 throw new UndeclaredThrowableException(t);
62 }
63 }
64
65 public final boolean deposit(BigDecimal paramBigDecimal) {
66 try {
67 return ((Boolean) this.h.invoke(this, m3,
68 new Object[] { paramBigDecimal })).booleanValue();
69 } catch (RuntimeException localRuntimeException) {
70 throw localRuntimeException;
71 } catch (Throwable localThrowable) {
72 throw new UndeclaredThrowableException(localThrowable);
73 }
74 }
75
76 static {
77 try {
78 m6 = Class.forName("BankAccount").getMethod("getId", new Class[0]);
79 m4 = Class.forName("BankAccount").getMethod("withdraw",
80 new Class[] { Class.forName("java.math.BigDecimal") });
81 m5 = Class.forName("BankAccount")
82 .getMethod("getName", new Class[0]);
83 m2 = Class.forName("java.lang.Object").getMethod("toString",
84 new Class[0]);
85 m0 = Class.forName("java.lang.Object").getMethod("hashCode",
86 new Class[0]);
87 m3 = Class.forName("BankAccount").getMethod("deposit",
88 new Class[] { Class.forName("java.math.BigDecimal") });
89 m1 = Class.forName("java.lang.Object").getMethod("equals",
90 new Class[] { Class.forName("java.lang.Object") });
91 } catch (NoSuchMethodException e) {
92 throw new NoSuchMethodError(e.getMessage());
93 } catch (ClassNotFoundException e) {
94 throw new NoClassDefFoundError(e.getMessage());
95 }
96 }
97 }
98
从动态代理生成的代码可以分析得到,所有的方法的调用,都会回调InvokeHanlder接口的实现类的invoke方法,并把实际调用的反射相关信息作为参数传给invoke方法。
Cglib Proxy AOP实现
cglib是一个开源项目! 是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。Spring很多地方借助该项目实现AOP的功能封装。
CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。通过使用CGLIB来为那些没有接口的类创建代理对象。
Cglib的Proxy与JDK Proxy还是有一定的相似的,下面的例子,给大家一个基本的演示
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->1 public class SimpleBean {
2
3 public void hello() {
4 System.out.println("hi matthew!");
5 }
6 }
Cglib 代理后(只给出了部分核心反编译后的Java代码)
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> 1 class SimpleBean$$EnhancerByCGLIB$$4c4a66a extends SimpleBean {
2 private static final Method CGLIB$hello$0$Method ;
3
4 public final void hello( ) {
5 if(!this.CGLIB$CONSTRUCTED)
6 {
7 super.hello();
8 return;
9
10 }
11 if(this.CGLIB$CALLBACK_0== null)
12 {
13 CGLIB$BIND_CALLBACKS(this);
14
15 }
16 if(this.CGLIB$CALLBACK_0!= null)
17 {
18 this.CGLIB$CALLBACK_0.intercept(this,SimpleBean$$EnhancerByCGLIB$$4c4a66a.CGLIB$hello$0$Method,SimpleBean$$EnhancerByCGLIB$$4c4a66a.CGLIB$emptyArgs,SimpleBean$$EnhancerByCGLIB$$4c4a66a.CGLIB$hello$0$Proxy);
19 return;
20
21 }
22 super.hello();
23 return;
24 catch(RuntimeException aRuntimeException2)
25 {
26 catch(Throwable aRuntimeException2)
27 {
28 UndeclaredThrowableException JdecGenerated57 = new UndeclaredThrowableException(
29 }
30 }
31
32 final void CGLIB$hello$0( )
33 {
34 super.hello();
35 return;
36 }
37
注: 从上面的实现代理来看,Cglib对于标识 final 关键字的class无法进行代理操作。
对于标识final的方法,也无法进行代理
分享到:
相关推荐
使用jdk proxy实现aop机制的一个小例子,写着给新手看看而已,老手们莫见笑
使用JDK中的Proxy技术实现AOP功能与使用CGLIB实现AOP功能
NULL 博文链接:https://countme.iteye.com/blog/1130188
AOP_1.入门及使用JDK中的Proxy技术实现
简单的动态代理实现代码!文档参考博文Spring学习(3)AOP初步—JDK动态代理
CGlib的Proxy实现AOP的示例、JDK的Proxy实现AOP的示例、通过spring注解方式实现AOP
AOP的实现机制,有文档、有测试实例. Java在JDK1.3后引入的动态代理机制,使我们可以在运行期动态的创建代理类。使用动态代理实现AOP需要有四个角色:被代理的类,被代理类的接口,织入器,和InvocationHandler,而...
自己写的小例子,供学习参考。 public class StaticProxy implements Hello{ private HelloSpecker helloSpecker; public StaticProxy() { } public StaticProxy(HelloSpecker helloSpecker) { ...
Jdk动态代理,基于接口的代理示例 InovactionHandler Proxy
有一天在用回调模版的时候,忽然间又想到jdk自带的Proxy类似乎不是怎么好用,为何不把其做成回调模版呢,可以将其改造称类似spring Aop 代码如下: package com.fjx.proxy.up.test; import ...
静态代理--不适合企业开发,适合初学者理解代理。 jdk动态代理--适合企业级开发,但是它要求必须面向接口编程,假如目标类没有实现接口...spring 的AOP功能中 会根据目标类是否实现了接口来判断使用 jdk Proxy还是cglib
1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP 2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP 3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间...
spring之AOP(动态代理),包括jdk动态代理和CGLib动态代理
proxy,jdkproxy-transaction,jdkproxy-salary,day02-itheima11-spring-08-cglibproxy,day02-itheima11-spring-09-aop.xml,day02-itheima11-spring-10-aop.xml.advice,day02-itheima11-spring-11-aop.xml.exception等...
使用JDK中的Proxy技术实现AOP 使用CGLib实现AOP功能
JDK1.2以后提供了动态代理的支持,程序员通过实现java.lang.reflect.InvocationHandler接口提供一个执行处理器,然后通过java.lang.reflect.Proxy得到一个代理对象,通过这个代理对象来执行商业方法,在商业方法被...
jdkproxy.AOP实践 这是练习jdkproxy.AOP的演示。
Spring AOP 使用的动态代理主要有两种方式:JDK 动态代理和 CGLIB 代理。 JDK 动态代理:用于代理实现了接口的类。Spring 会使用 java.lang.reflect.Proxy 类来创建代理对象。 CGLIB 代理:用于代理没有实现接口的...
* * * * JDK动态代理 JDK动态代理 JDK动态代理是通过java.lang.reflect.Proxy 类来实现的,我们可以调用Proxy类的newProxyInstance()方法来创建代理对象。对于使用业务接口的类,Spring默认会使用JDK动态代理来实现...
Java 代理 代理模式 静态代理与动态代理 常见的动态代理实现 JDK Proxy CGLIB JDK Proxy 和 CGLIB 的对比 动态代理的实际应用 Spring AOP