No_1 手写Proxy
手写动态代理主要原理:
userDAO=(UserDAO)Proxy.newProxyinstance(classloader,interfaces[],new MyInvocationHandler(targer);
userDAO.save();
public class AppMain {
//上课老师的代码
    public static void main(String[] args) {
        UserDAO userDAO = new UserDAO();
        Object proxyObject = newProxy(userDAO);
        IDAO idao = (IDAO) proxyObject;
        idao.save();
    }
    public static Object newProxy(Object target) {
        // 生成动态类,类的方法来之接口,得到Class对象
        /// class[]数组中放的是UserDAO的所有接口类信息
        Class[] interfaces = target.getClass().getInterfaces();
        // 需要类加载器
        ClassLoader classLoader = target.getClass().getClassLoader();
        // 回调myHandler
        MyInvocationHandler myHandler = new MyInvocationHandler(target);
        // 调用java动态处理框架
        Object proxyObject = Proxy.newProxyInstance(classLoader, interfaces, new MyInvocationHandler(target) {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // TODO Auto-generated method stub
                System.out.println("日志");
                return super.invoke(target, method, args);
            }
        });
        return proxyObject;
    }
    static class MyInvocationHandler implements InvocationHandler {
        Object target;
        public MyInvocationHandler(Object target) {
            super();
            this.target = target;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("日志");
            method.invoke(target, args);
            return null;
        }
    }
}
1=. class ZProxy { public Object newProxyinstance( classLoader, interfaces, new MyInvocationHandler(target){
1.拼写字符串,public class MyProxy { @1 有一个构造方法 接受handler; @2 调用方法query{ 里面是handler.invoke(this,method,arges)} ,注意这个第一个参数是this对象;
生成的动态代理对象
package com.jv.own; import com.jv.own.UserDao;
import java.lang.reflect.Method; import com.jv.own.MyInvocationHandler; public class MyProxy implements UserDao{ private MyInvocationHandler handler;
public MyProxy(MyInvocationHandler handler){
this.handler = handler;
} public com.jv.own.User query(java.lang.String p1){
try{
Object[] args = new Object[]{p1};
Method method = com.jv.own.UserDao.class.getMethod("query",Class.forName("java.lang.String"));
return (com.jv.own.User)handler.invoke(this,method,args);
}catch(Throwable e){
return null;
}
}
}
2. 根据生成的MyProxy类,利用构造方法生成对象,同时传入handler对象;return constructors[0].newInstance(handler);
URL[] urls = new URL[]{new URL("file:f\\\\projects\\own\\spring-framework-master\\proxy\\out\\production\\classes")};
        URLClassLoader urlClassLoader = new URLClassLoader(urls);
        Class clazz = urlClassLoader.loadClass("com.jv.own.MyProxy");
        //############################################实例化############################################
        //返回
        Constructor[] constructors = clazz.getConstructors();
        constructors[0].newInstance(handler);
        return constructors[0].newInstance(handler);
3. done
第一个类
package com.jv.own; import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader; import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider; public class MyProxyUtil { private static final String l = "\n\r";
private static final String t = "\t"; public static Object newInstance(ClassLoader classLoader,Class[] interfaces,MyInvocationHandler handler) throws Exception{
StringBuilder sb = new StringBuilder();
StringBuilder sbImport = new StringBuilder();
StringBuilder sbImplements = new StringBuilder();
StringBuilder sbMethods = new StringBuilder(); //############################################生成源代码############################################
//包定义
sb.append("package com.jv.own;").append(l+l);
if(interfaces == null || interfaces.length==0){
throw new Exception("接口不能为空");
}
//生成导入和implements
for (Class anInterface : interfaces) {
sbImport.append("import "+anInterface.getName()+";"+l);
sbImplements.append(anInterface.getSimpleName()+",");
}
sbImport.append("import java.lang.reflect.Method;").append(l+l);
sbImport.append("import com.jv.own.MyInvocationHandler;").append(l+l);
sb.append(sbImport.toString());
String temp = sbImplements.toString().substring(0,sbImplements.toString().lastIndexOf(","));
//类定义
sb.append("public class MyProxy implements ").append(temp).append("{").append(l).append(l);
sb.append(t+"private MyInvocationHandler handler;").append(l);
//构造函数
sb.append(t+"public MyProxy(").append("MyInvocationHandler handler){").append(l);
sb.append(t+t+"this.handler = handler;").append(l).append(t).append("}").append(l).append(l);
//生成接口里面所有的
for (Class anInterface : interfaces) {
Method[] methods = anInterface.getMethods();
for (Method method : methods) {
String parameter = "";
String parameterType = "";
int i = 1;
for(Class cl:method.getParameterTypes()){
parameter += cl.getName() + " p" + i++ +",";
parameterType += "Class.forName(\""+cl.getTypeName()+"\")"+",";
}
if(parameter!=null&&!parameter.equals("")) {
parameter = parameter.substring(0, parameter.lastIndexOf(","));
parameterType = parameterType.substring(0, parameterType.lastIndexOf(","));
}
sbMethods.append(t).append("public ").append(method.getReturnType().getName()).append(" ").append(method.getName())
.append("(").append(parameter).append("){").append(l+t+t);
sbMethods.append("try{").append(l+t+t+t);
String args = "Object[] args = new Object[]{";
for(int j=1;j<i;j++){
args += "p"+j+",";
}
args = args.substring(0,args.lastIndexOf(","))+"};";
sbMethods.append(args).append(l+t+t+t); StringBuilder methodContent = new StringBuilder();
//methodContent.append("Method method = Class.forName(\""+anInterface.getTypeName()+"\").getMethod(\""+method.getName()+"\","+parameterType+");");
methodContent.append("Method method = "+anInterface.getName()+".class.getMethod(\""+method.getName()+"\","+parameterType+");");
sbMethods.append(methodContent.toString()).append(l+t+t+t); if(method.getReturnType().getName().equals("void")){
sbMethods.append("handler.invoke(this,method,args);").append(l+t+t);
}else{
sbMethods.append("return "+"("+method.getReturnType().getName()+")"+"handler.invoke(this,method,args);").append(l+t+t);
}
sbMethods.append("}catch(Throwable e){"+l+t+t+t+"return null;"+l+t+t+"}"+l+t);
sbMethods.append("}").append(l);
}
}
sb.append(sbMethods.toString()); sb.append("}");
System.out.println(sb.toString()); //############################################将源代码写入磁盘文件############################################
String filePath = MyProxyUtil.class.getResource("").getPath() + "MyProxy.java";
System.out.println(filePath);
FileWriter fileWriter = new FileWriter(filePath);
fileWriter.write(sb.toString());
fileWriter.flush();
fileWriter.close();
//############################################编译源代码############################################
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable iterable = fileManager.getJavaFileObjects(filePath);
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, null, null, iterable);
task.call();
fileManager.close();
//############################################将文件通过URLClassLocader或者自定义ClassLoader进行加载############################################
URL[] urls = new URL[]{new URL("file:f\\\\projects\\own\\spring-framework-master\\proxy\\out\\production\\classes")}; URLClassLoader urlClassLoader = new URLClassLoader(urls);
Class clazz = urlClassLoader.loadClass("com.jv.own.MyProxy");
//############################################实例化############################################ //返回
Constructor[] constructors = clazz.getConstructors();
constructors[0].newInstance(handler);
return constructors[0].newInstance(handler);
}
}
第二个handler接口
package com.jv.own;
import java.lang.reflect.Method;
public interface MyInvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable;
}
第三个主app
package com.jv.own;
public class TestMyProxy {
    public static void main(String[] args) {
        MyInvocationHandler handler = new MyOwnInvocationHandler(new UserDaoImpl());
        try {
            UserDao dao = (UserDao)MyProxyUtil.newInstance(com.jv.own.UserDao.class.getClassLoader(),new Class[]{UserDao.class},handler);
            dao.query("a");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
第四个接口
package com.jv.own;
public class User {
    private String userName;
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
}
------------------------------
package com.jv.own;
public interface UserDao {
    User query(String name);
}
--------------------------------
package com.jv.own;
public class UserDaoImpl implements UserDao {
    @Override
    public User query(String name) {
        System.out.println("UserDaoImpl execute query");
        return null;
    }
}
自己的handler
package com.jv.own;
import java.lang.reflect.Method;
public class MyOwnInvocationHandler implements MyInvocationHandler{
    private UserDao target;
    public MyOwnInvocationHandler(UserDao target){
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("invoke before");
        method.invoke(target,args);
        System.out.println("invoke after");
        return null;
    }
}
托管地址
https://github.com/atzhangsan/common_projects.git
atzhang5月29
No_1 手写Proxy的更多相关文章
- springmvc 动态代理  JDK实现与模拟JDK纯手写实现。
		
首先明白 动态代理和静态代理的区别: 静态代理:①持有被代理类的引用 ② 代理类一开始就被加载到内存中了(非常重要) 动态代理:JDK中的动态代理中的代理类是动态生成的.并且生成的动态代理类为$Pr ...
 - Android 手写Binder 教你理解android中的进程间通信
		
关于Binder,我就不解释的太多了,网上一搜资料一堆,但是估计还是很多人理解的有困难.今天就教你如何从 app层面来理解好Binder. 其实就从我们普通app开发者的角度来看,仅仅对于androi ...
 - JDK动态代理深入理解分析并手写简易JDK动态代理(下)
		
原文同步发表至个人博客[夜月归途] 原文链接:http://www.guitu18.com/se/java/2019-01-05/27.html 作者:夜月归途 出处:http://www.guitu ...
 - JDK动态代理深入理解分析并手写简易JDK动态代理(上)
		
原文同步发表至个人博客[夜月归途] 原文链接:http://www.guitu18.com/se/java/2019-01-03/27.html 作者:夜月归途 出处:http://www.guitu ...
 - 依据ECMA规范,手写一个bind函数
		
Function.prototype.bind 函数,参见ECMA规范地址 如题,这次来实现一个boundFunction函数,不挂载在Function.prototype上,而是一个单独声明的函数. ...
 - Atitit s2018.2 s2 doc list on home ntpc.docx    \Atiitt uke制度体系  法律 法规 规章 条例 国王诏书.docx \Atiitt 手写文字识别  讯飞科大 语音云.docx \Atitit 代码托管与虚拟主机.docx \Atitit 企业文化  每日心灵 鸡汤 值班 发布.docx \Atitit 几大研发体系对比 Stage-Gat
		
Atitit s2018.2 s2 doc list on home ntpc.docx \Atiitt uke制度体系 法律 法规 规章 条例 国王诏书.docx \Atiitt 手写文字识别 ...
 - 基于tensorflow的MNIST手写识别
		
这个例子,是学习tensorflow的人员通常会用到的,也是基本的学习曲线中的一环.我也是! 这个例子很简单,这里,就是简单的说下,不同的tensorflow版本,相关的接口函数,可能会有不一样哟.在 ...
 - 纯手写Myatis框架
		
1.接口层-和数据库交互的方式 MyBatis和数据库的交互有两种方式: 使用传统的MyBatis提供的API: 使用Mapper接口: 2.使用Mapper接口 MyBatis 将配置文件中的每一个 ...
 - 代理模式精讲(手写JDK动态代理)
		
代理模式是一种架构型模式,表现出来就是一个类代表另一个类的功能,一般用在想对访问一个类的时候做一些控制,同时又不想影响正常的业务,这种代理模式在现实的生活中应用的也非常的广泛,我用穷举法给举几个好理解 ...
 
随机推荐
- 【CMD】修改文件夹的属性
			
将 d:\文件夹 添加 只读 属性: attrib +r d:\文件夹 /d 将 d:\文件夹 去掉 只读 属性: attrib -r d:\文件夹 /d 其他属性可以参考帮助文件:
 - xxl-job执行器的注册
			
一.执行器注册流程 二.具体流程 1.注册监控线程 //类:JobRegistryHelper.java:方法:public void start() registryMonitorThread = ...
 - 在Intellij IDEA中查看TestNG自带的测试报告
			
执行TestNG框架的测试用例,会生成测试报告.如果在IDEA中看不到,可做如下配置. 1. 点击IDEA工具栏中Run->Edit Configuration菜单,或者直接点击右上角编辑配置的 ...
 - 『心善渊』Selenium3.0基础 — 2、Selenium测试框架环境搭建(Windows)
			
目录 1.浏览器安装 2.浏览器驱动下载 (1)ChromeDriver for Chrome (2)Geckodriver for Firefox (3)IEDriverServer for IE ...
 - 机器人路径规划其二 A-Star Algorithm【附动态图源码】
			
首先要说明的是,机器人路径规划与轨迹规划属于两个不同的概念,一般而言,轨迹规划针对的对象为机器人末端坐标系或者某个关节的位置速度加速度在时域的规划,常用的方法为多项式样条插值,梯形轨迹等等,而路径规划 ...
 - 痞子衡嵌入式:在串口波特率识别实例里逐步展示i.MXRT上提升代码执行性能的十八般武艺
			
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是在串口波特率识别实例里逐步展示i.MXRT上提升代码执行性能的十八般武艺. 恩智浦 MCU SE 团队近期一直在加班加点赶 SBL 项目 ...
 - 【Linux】通过shell脚本对mysql的增删改查以及my.cnf的配置
			
目录 shell操作mysql 1.获取mysql默认密码 2.修改my.cnf文件 3.shell创建mysql数据库 4.shell创建mysql表 5.shell添加数据 6.shell删除数据 ...
 - [Django REST framework - 自动生成接口文档、分页]
			
[Django REST framework - 自动生成接口文档.分页] 自动生成接口文档 # 后端人员写好接口,编写接口文档,给前端人员看,前端人员依照接口文档开发 # 公司里主流 -后端,使用w ...
 - CRM系统选型时的参考哪些方面
			
企业不论在制定营销策略或是在进行CRM系统选型时,首先都是要了解自身的需求.每一家企业的情况和需求都有很大差异,CRM系统的功能也都各有偏重.有些CRM偏重销售管理.有些注重于营销自动化.有些则侧重于 ...
 - iOS导入其他APP下载的文件(用其他应用打开)
			
今天给自己的APP新增了一个小功能 可以打开iOS其他APPTXT 文件,一个很小的功能,做阅读APP的小伙伴不要错过. 附上APP地址: 一阅阅读 有想看小说的小伙伴可以试下 支持换源 支持自定义书 ...