jdk动态代理学习
在jdk的好多底层代码中很多都使用jdk的动态代理,下面就写写简单的代码来look look.
老规矩先上代码:
public interface SayDao {
public String sayChinese();
public String sayEnglish();
}
public class SayDaoImpl implements SayDao {
@Override
public String sayChinese() {
return "我就是我!";
}
@Override
public String sayEnglish() {
return "I am tom_plus!";
}
}
public class JDBCProxy implements InvocationHandler {
private Object target;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("invoke begin!");
return method.invoke(target,args);
}
public Object bind(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
}
public class JDBCProxyTest {
public static void main(String[] args) {
JDBCProxy jdbcProxy = new JDBCProxy();
SayDao sayDao = (SayDao) jdbcProxy.bind(new SayDaoImpl());
String s = sayDao.sayChinese();
System.out.println(s);
System.out.println("----------------");
printClassDefinition(sayDao.getClass());
}
public static String getModifier(int modifier) {
String result = "";
switch(modifier){
case Modifier.PRIVATE:
result = "private";
case Modifier.PUBLIC:
result = "public";
case Modifier.PROTECTED:
result = "protected";
case Modifier.ABSTRACT :
result = "abstract";
case Modifier.FINAL :
result = "final";
case Modifier.NATIVE :
result = "native";
case Modifier.STATIC :
result = "static";
case Modifier.SYNCHRONIZED :
result = "synchronized";
case Modifier.STRICT :
result = "strict";
case Modifier.TRANSIENT :
result = "transient";
case Modifier.VOLATILE :
result = "volatile";
case Modifier.INTERFACE :
result = "interface";
}
return result;
}
public static void printClassDefinition(Class clz){
String clzModifier = getModifier(clz.getModifiers());
if(clzModifier!=null && !clzModifier.equals("")){
clzModifier = clzModifier + " ";
}
String superClz = clz.getSuperclass().getName();
if(superClz!=null && !superClz.equals("")){
superClz = "extends " + superClz;
}
Class[] interfaces = clz.getInterfaces();
String inters = "";
for(int i=0; i<interfaces.length; i++){
if(i==0){
inters += "implements ";
}
inters += interfaces[i].getName();
}
System.out.println(clzModifier +clz.getName()+" " + superClz +" " + inters );
System.out.println("{");
Field[] fields = clz.getDeclaredFields();
for(int i=0; i<fields.length; i++){
String modifier = getModifier(fields[i].getModifiers());
if(modifier!=null && !modifier.equals("")){
modifier = modifier + " ";
}
String fieldName = fields[i].getName();
String fieldType = fields[i].getType().getName();
System.out.println(" "+modifier + fieldType + " "+ fieldName + ";");
}
System.out.println();
Method[] methods = clz.getDeclaredMethods();
for(int i=0; i<methods.length; i++){
Method method = methods[i];
String modifier = getModifier(method.getModifiers());
if(modifier!=null && !modifier.equals("")){
modifier = modifier + " ";
}
String methodName = method.getName();
Class returnClz = method.getReturnType();
String retrunType = returnClz.getName();
Class[] clzs = method.getParameterTypes();
String paraList = "(";
for(int j=0; j<clzs.length; j++){
paraList += clzs[j].getName();
if(j != clzs.length -1 ){
paraList += ", ";
}
}
paraList += ")";
clzs = method.getExceptionTypes();
String exceptions = "";
for(int j=0; j<clzs.length; j++){
if(j==0){
exceptions += "throws ";
}
exceptions += clzs[j].getName();
if(j != clzs.length -1 ){
exceptions += ", ";
}
}
exceptions += ";";
String methodPrototype = modifier +retrunType+" "+methodName+paraList+exceptions;
System.out.println(" "+methodPrototype );
}
System.out.println("}");
}
}
我的视角:
动态代理其实就是Proxy类动态的根据指定的所有接口生成一个class,该class会继承Proxy类,并实现所有指定的接口(在参数中传入的接口数组);然后再利用指定的classloader将 class加载进系统,最后生成这样一个类的对象,并初始化该对象的一些值,如invocationHandler,以即所有的接口对应的Method成员。 初始化之后将对象返回给调用的客户端。这样客户端拿到的就是一个实现所有的接口的Proxy对象。
从代码角度:
com.sun.proxy.$Proxy0 extends java.lang.reflect.Proxy implements com.springapp.test.SayDao
{
java.lang.reflect.Method m1;
java.lang.reflect.Method m0;
java.lang.reflect.Method m3;
java.lang.reflect.Method m4;
java.lang.reflect.Method m2;
boolean equals(java.lang.Object);
java.lang.String toString();
int hashCode();
java.lang.String sayChinese();
java.lang.String sayEnglish();
}
具体细节:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
参数一:类加载器,把创建的代理类class加载进系统。
参数二:被代理对象实现的接口 class数组
参数三:调度处理程序类,内有invoke()方法,代理的核心就是调InvocationHandler类的invoke(Object proxy, Method method, Object[] args)方法
,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。
注意点:Object proxy 这个参数,代表的是代理类对象。
调用这个方法,返回代理类 class。
jdk动态代理学习的更多相关文章
- java jdk动态代理学习记录
转载自: https://www.jianshu.com/p/3616c70cb37b JDK自带的动态代理主要是指,实现了InvocationHandler接口的类,会继承一个invoke方法,通过 ...
- JDK动态代理学习心得
JDK动态代理是代理模式的一种实现方式,其只能代理接口.应用甚为广泛,比如我们的Spring的AOP底层就有涉及到JDK动态代理(此处后面可能会分享) 1.首先来说一下原生的JDK动态代理如何实现: ...
- AOP学习心得&jdk动态代理与cglib比较
什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入 ...
- aop学习总结一------使用jdk动态代理简单实现aop功能
aop学习总结一------使用jdk动态代理实现aop功能 动态代理:不需要为目标对象编写静态代理类,通过第三方或jdk框架动态生成代理对象的字节码 Jdk动态代理(proxy):目标对象必须实现接 ...
- 动态代理学习(二)JDK动态代理源码分析
上篇文章我们学习了如何自己实现一个动态代理,这篇文章我们从源码角度来分析下JDK的动态代理 先看一个Demo: public class MyInvocationHandler implements ...
- 动态代理学习(一)自己动手模拟JDK动态代理
最近一直在学习Spring的源码,Spring底层大量使用了动态代理.所以花一些时间对动态代理的知识做一下总结. 我们自己动手模拟一个动态代理 对JDK动态代理的源码进行分析 文章目录 场景: 思路: ...
- 学习CGLIB与JDK动态代理的区别
动态代理 代理模式是Java中常见的一种模式.代理又分为静态代理和动态代理.静态代理就是显式指定的代理,静态代理的优点是由程序员自行指定代理类并进行编译和运行,缺点是一个代理类只能对一个接口的实现类进 ...
- Java学习笔记--JDK动态代理
1.JDK动态代理 JDK1.3之后,Java提供了动态代理的技术,允许开发者在运行期创建接口的代理实例.JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和 ...
- java学习笔记(中级篇)—JDK动态代理
一.什么是代理模式 相信大家都知道代理商这个概念,在商业中,代理商无处不在.假设你要去买东西,你不可能去找真正的厂家去买,也不可能直接跟厂家提出需求,代理商就是这中间的一桥梁,连接买家和厂商.你要买或 ...
随机推荐
- http://www.cnblogs.com/meiCode/p/5896239.html
http://www.cnblogs.com/meiCode/p/5896239.html
- 思维题(转换) HDU 4370 0 or 1
题目传送门 题意:题目巨晦涩的传递出1点和n点的初度等于入度等于1, 其余点出度和入度相等 分析:求最小和可以转换成求最短路,这样符合条件,但是还有一种情况.1点形成一个环,n点也形成一个环,这样也是 ...
- Linux 积累
Unable to locate package 解决办法: sudo apt-get update
- [转]HTML5本地存储——Web SQL Database
在HTML5 WebStorage介绍了html5本地存储的Local Storage和Session Storage,这两个是以键值对存储的解决方案,存储少量数据结构很有用,但是对于大量结构化数据就 ...
- HTML5 postMessage 和 onmessage API 详细应用
随着 HTML5 的发展,了解并熟悉 HTML5 的 API 接口是非常重要的.postMessage(send) 和 onmessage 此组 API 在 HTML5 中有着广泛的应用,比如 Web ...
- dede表单修改默认必填
默认的dedecms自定义表单却没有必填项的设置,如果要设置织梦自定义表单的必填项,需要进行额外的修改! 方法一:通过修改程序源文件实现 1.在plus文件夹下找到diy.php文件,对其进行编辑,在 ...
- sqlserver数据库 去除字段中空格,换行符,回车符(使用replace语句)
SQL中可以使用Replace函数来对某个字段里的某些字符进行替换操作,语法如下: 语法 REPLACE ( original-string, search-string, replace-strin ...
- BZOJ3654 : 图样图森破
考虑枚举回文中心,然后向两边扩展,当匹配到当前串的边界的时候,枚举下一个串接上. 这个过程可以通过记忆化搜索来完成,设: $f[i][0]$表示对于$i$这个位置,$[i,串结尾]$等待匹配的最长回文 ...
- BZOJ3764 : Petya的序列
首先如果一段连续子序列里没有任何幸运数,那么显然可以缩成一个点. 设幸运数个数为$m$,那么现在序列长度是$O(m)$的,考虑暴力枚举$R_1$,然后从右往左枚举$L_1$. 每次碰到一个幸运数,就将 ...
- Zend studio 10.6 配置XDEBUG
1. 查看PHP版本,下载XDebug 然后去网站http://xdebug.org/download.php下载相应的XDEBUG, 把下载好的文件放到相应的PHP下的EXT目录下,替换之前 ...