【深入JAVA】JDK静动态代理
2015-06-10 18:16
429 查看
静态代理:是由程序员创建或特定工具自动生成源代码,再对其进行编译,在程序运行前,代理类的.class文件就已经存在
动态代理:在程序运行时,代理类的.class文件是运用反射机制动态创建而成
一、静态代理
1> 定义一个接口Count
总结:一个代理类只能为一个接口服务,如果需要代理的接口很多,那么开发过程中将编写大量的代理类,而且所有的代理操作除了调用的方法不一样,其他的操作都一样,这样就造成了大量的重复工作,不会偷懒的程序猿不是好的攻城狮,因此我们可以通过一个代理类完成全部的代理功能,那么此时就必须使用动态代理了。
二、JDK动态代理
1>自定义一个接口(同上)
2>编写实现类(同上)
3>编写JDK核心代理类
总结:JDK动态代理依靠接口实现,没有实现接口的类则不能使用JDK动态代理,这也是JDK动态代理的一个缺陷吧,不过在cglib中得到了弥补.
这个时候我们可以看看程序运行过程中生成的代理类,run上面的main方法之后可以在当前工程根目录中发现一个$Proxy0.class文件,使用反编译工具打开后可以看到具体内容,下面是我测试代码生成的的.class
需要解释的地方已经注释在代码中,应该还算清晰明了,后续会贴上cglib的代理还有Spring AOP动态代理的应用
------------------------------
end by wuxiao
动态代理:在程序运行时,代理类的.class文件是运用反射机制动态创建而成
一、静态代理
1> 定义一个接口Count
/** * 自定义接口 * @author xwu * */ public interface Count { //查看账户 public void queryCount(); //更新账户 public void updateCount(); }2>编写实现类
package com.wuxiao.proxy.staticProxy; /** * 接口实现类 * * @author xwu * */ public class CountImpl implements Count { public void queryCount() { // TODO Auto-generated method stub System.out.println("调用查看账户方法..."); } public void updateCount() { // TODO Auto-generated method stub System.out.println("调用更新账户方法..."); } }3>编写Count的代理类
package com.wuxiao.proxy.staticProxy; /** * Count的代理类CountProxy * * @author xwu * */ public class CountProxy implements Count { private CountImpl countImpl; public CountProxy(CountImpl countImpl) { this.countImpl = countImpl; } public void queryCount() { System.out.println("方法调用之前..."); countImpl.queryCount();// 调用委托方法 System.out.println("方法调用之后..."); } public void updateCount() { System.out.println("方法调用之前..."); countImpl.updateCount();// 调用委托方法 System.out.println("方法调用之后..."); } }4>编写测试类
package com.wuxiao.proxy.staticProxy; /** * 静态代理测试类 * * @author xwu * */ public class StaticProxyTest { public static void main(String[] args) { CountImpl countImpl = new CountImpl(); CountProxy proxy = new CountProxy(countImpl); proxy.queryCount(); proxy.updateCount(); } }5>看一下运行效果
方法调用之前... 调用查看账户方法... 方法调用之后... 方法调用之前... 调用更新账户方法... 方法调用之后...
总结:一个代理类只能为一个接口服务,如果需要代理的接口很多,那么开发过程中将编写大量的代理类,而且所有的代理操作除了调用的方法不一样,其他的操作都一样,这样就造成了大量的重复工作,不会偷懒的程序猿不是好的攻城狮,因此我们可以通过一个代理类完成全部的代理功能,那么此时就必须使用动态代理了。
二、JDK动态代理
1>自定义一个接口(同上)
2>编写实现类(同上)
3>编写JDK核心代理类
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 切面 * * @author xwu * */ public class JDKProxyFactory implements InvocationHandler { private Object proxyObject; // 目标对象 public Object createProxyInstance(Object proxyObject) { this.proxyObject = proxyObject; // 生成代理类的字节码加载器 ClassLoader classLoader = proxyObject.getClass().getClassLoader(); // 需要代理的接口,被代理实现的多个接口都必须定义在这里(这是一个缺陷,cglib弥补了这一缺陷) Class<?>[] proxyInterface = proxyObject.getClass().getInterfaces(); // 织入器,织入代码并生成代理类 return Proxy.newProxyInstance(classLoader, proxyInterface, this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { PersonServiceBean bean = (PersonServiceBean) this.proxyObject; Object result = null; // 控制哪些用户切入逻辑,这里是做了用户名过滤,当然你也可以做其他事情 if (bean.getUser() != null) { // 执行原有逻辑 result = method.invoke(this.proxyObject, args); } return result; } }4>编写测试类
package com.wuxiao.proxy; /** * 通过main方法,并设置sun.misc.ProxyGenerator.saveGeneratedFiles参数可以查看生成的proxy文件 * * @author xwu * */ public class JDKProxyTest { public static void main(String[] args) { // 设置此系统属性,以查看代理类文件 System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); JDKProxyFactory factory = new JDKProxyFactory(); PersonService bean = (PersonService) factory.createProxyInstance(new PersonServiceBean("lucy")); bean.save("abc");// 用户lucy有权限 PersonService bean2 = (PersonService) factory.createProxyInstance(new PersonServiceBean()); bean2.save("abc");// 用户为null没有权限 } }5>看看运行效果
这是save方法
总结:JDK动态代理依靠接口实现,没有实现接口的类则不能使用JDK动态代理,这也是JDK动态代理的一个缺陷吧,不过在cglib中得到了弥补.
这个时候我们可以看看程序运行过程中生成的代理类,run上面的main方法之后可以在当前工程根目录中发现一个$Proxy0.class文件,使用反编译工具打开后可以看到具体内容,下面是我测试代码生成的的.class
import com.wuxiao.proxy.PersonService; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; //代理继承了Proxy类,并实现了Proxy.newProxyInstance中传入的接口 public final class $Proxy0 extends Proxy implements PersonService { //这些方法在下面的static体中进行了初始化 private static Method m5; private static Method m3; private static Method m1; private static Method m0; private static Method m4; private static Method m2; //构造函数,接收一个InvocationHandler作为参数,这就是为什么Proxy.newProxyInstance方法里 //可以通过InvocationHandler实例作为参数来反射获取Constructer实例 public $Proxy0(InvocationHandler paramInvocationHandler) throws { super(paramInvocationHandler); } //同下面的save方法 public final void update(Integer paramInteger, String paramString) throws { try { this.h.invoke(this, m5, new Object[] { paramInteger, paramString }); return; } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { } throw new UndeclaredThrowableException(localThrowable); } //下面通过这个save方法来看看代理对象中的方法是如何调用的 public final void save(String paramString) throws { try { //全部是通过调用InvocationHandler的invoke方法,传入对应的方法和参数 this.h.invoke(this, m3, new Object[] { paramString }); return; } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { } throw new UndeclaredThrowableException(localThrowable); } public final boolean equals(Object paramObject) throws { try { return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue(); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { } throw new UndeclaredThrowableException(localThrowable); } public final int hashCode() throws { try { return ((Integer)this.h.invoke(this, m0, null)).intValue(); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { } throw new UndeclaredThrowableException(localThrowable); } public final String getPersonName(Integer paramInteger) throws { try { return (String)this.h.invoke(this, m4, new Object[] { paramInteger }); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { } throw new UndeclaredThrowableException(localThrowable); } public final String toString() throws { try { return (String)this.h.invoke(this, m2, null); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { } throw new UndeclaredThrowableException(localThrowable); } static { try { m5 = Class.forName("com.wuxiao.proxy.PersonService").getMethod("update", new Class[] { Class.forName("java.lang.Integer"), Class.forName("java.lang.String") }); m3 = Class.forName("com.wuxiao.proxy.PersonService").getMethod("save", new Class[] { Class.forName("java.lang.String") }); m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); m4 = Class.forName("com.wuxiao.proxy.PersonService").getMethod("getPersonName", new Class[] { Class.forName("java.lang.Integer") }); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); return; } catch (NoSuchMethodException localNoSuchMethodException) { throw new NoSuchMethodError(localNoSuchMethodException.getMessage()); } catch (ClassNotFoundException localClassNotFoundException) { } throw new NoClassDefFoundError(localClassNotFoundException.getMessage()); } }
需要解释的地方已经注释在代码中,应该还算清晰明了,后续会贴上cglib的代理还有Spring AOP动态代理的应用
------------------------------
end by wuxiao
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树
- [原创]java局域网聊天系统