jdk动态代理底层实现

静态代理

继承

代理对象继承目标对象,重写目标对象的方法

目标对象:

package dao;

public class UserDaoImpl {

    public void query(String name)
    {
        System.out.println("query name=" + name);
    }
}

代理对象:

package proxy;

import dao.UserDaoImpl;

public class LogUserProxy extends UserDaoImpl {

    @Override
    public void query(String name) {
        System.out.println("log name=" + name);
        super.query(name);
    }
}

聚合

目标对象和代理对象实现同一个接口,并且代理对象当中包含着抽象对象。

抽象对象:

package dao;

public interface UserDao {

    void query(String name);
}

目标对象:

package dao;

public class UserDaoImpl implements UserDao{

    public void query(String name)
    {
        System.out.println("query name=" + name);
    }
}

代理对象:

package proxy;

import dao.UserDao;
import dao.UserDaoImpl;

public class LogUserProxy implements UserDao {

    private UserDao userDao;
    public LogUserProxy(UserDao userDao)
    {
        this.userDao=userDao;
    }

    public void query(String name) {
        System.out.println("log...");
        userDao.query(name);
    }
}

package proxy;

import dao.UserDao;

public class TimeUserProxy implements UserDao {
    private UserDao userDao;
    public TimeUserProxy(UserDao userDao)
    {
        this.userDao=userDao;
    }

    public void query(String name) {
        System.out.println("time...");
        userDao.query(name);
    }
}

测试:

package test;

import dao.UserDao;
import dao.UserDaoImpl;
import proxy.LogUserProxy;
import proxy.TimeUserProxy;

public class Test {

    public static void main(String[] args) {

        UserDao userDao=new UserDaoImpl();
        UserDao proxy1=new LogUserProxy(userDao);
        UserDao proxy2=new TimeUserProxy(proxy1);
        proxy2.query("Jack");
    }
}

在这里插入图片描述

动态代理

编写代理类

在这里插入图片描述

package test;

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

public class ProxyUtil {


    /*
    * 通过拼接字符串得到一个Java文件
    * 编译成为一个class
    * 通过反射得到一个对象
    * return*/

    public static Object newProxyInstance(Object target) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

        String content="";//java文件的内容
        String packageContent="package proxy;";//目标类所在包                                    package proxy;
        Class targetInfo=target.getClass().getInterfaces()[0];//得到目标类实现的接口
        String targetInfoName=targetInfo.getSimpleName();//得到接口名(不包含包名)
        String importContent="import "+targetInfo.getName()+";";//得到导入的接口的完全限定名        import dao.UserDao;
        String classContent="public class $Proxy implements "+targetInfoName+"{";      //类名
        String fieldContent="private "+targetInfoName+" target;";
        String constructContent="public $Proxy("+targetInfoName+" target){"//构造方法
                +"this.target=target;}";
        String methodsContent="";//得到所有的方法
        Method[] declaredMethods=targetInfo.getDeclaredMethods();
        for(Method method:declaredMethods)
        {
            String methodName=method.getName();//得到方法名
            Class returnType=method.getReturnType();//得到返回类型
            Class<?>[] parameterTypes = method.getParameterTypes();//得到方法参数列表
            String argsContent="";//方法参数
            String argsName="";//方法参数对象
            int i=0;
            for(Class<?> parameterType:parameterTypes)
            {
                String simpleName = parameterType.getSimpleName();
                argsContent+=simpleName+" p"+i+",";
                argsName+="p "+i+",";
                i++;
            }
            if (argsContent.length()>0) {
                argsContent=argsContent.substring(0,argsContent.lastIndexOf(",")-1);
                argsName=argsName.substring(0,argsName.lastIndexOf(",")-1);
            }
            methodsContent="public "+returnType+" "+methodName+"("+argsContent+"){"
                    +"System.out.println(\"log...\");"
                    +"target."+methodName+"("+argsName+");}";
        }
        content+=packageContent+importContent+classContent+fieldContent+constructContent+methodsContent+"}";

        //写到磁盘上
        File file=new File("d:\\proxy\\$Proxy.java");
        if(!file.exists())
        {
            file.createNewFile();
        }
        FileWriter fileWriter=new FileWriter(file);
        fileWriter.write(content);
        fileWriter.flush();
        fileWriter.flush();

        //编译得到class文件
        JavaCompiler compiler= ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
        Iterable units=fileManager.getJavaFileObjects(file);
        JavaCompiler.CompilationTask task=compiler.getTask(null,fileManager,null,null,null,units);
        task.call();
        fileManager.close();

        //加载磁盘上的class文件
        URL[] urls=new URL[]{new URL("file:d\\\\")};
        URLClassLoader urlClassLoader=new URLClassLoader(urls);
        Class $Proxy = urlClassLoader.loadClass("proxy.$Proxy");
        Constructor constructor = $Proxy.getConstructor(targetInfo);
        Object o = constructor.newInstance(target);

        return o;

    }
}

#生成的Java文件

package proxy;

import dao.UserDao;

public class $Proxy implements UserDao {
    private UserDao target;

    public $Proxy(UserDao target) {
        this.target = target;
    }

    public void query(String p) {
        System.out.println("log...");
        target.query(p);
    }
}

测试

package test;

import dao.UserDao;
import dao.UserDaoImpl;
import proxy.LogUserProxy;
import proxy.TimeUserProxy;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test {

    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {

        UserDao userDao=new UserDaoImpl();
        UserDao proxy = (UserDao)ProxyUtil.newProxyInstance(userDao);
        proxy.query("Jack");

    }


}

参考函数

getInterfaces()

public static void main(String[] args) {

        UserDaoImpl userDao = new UserDaoImpl();
        Class iface=userDao.getClass().getInterfaces()[0];
        System.out.println(iface);
        System.out.println(iface.getSimpleName());
        System.out.println(iface.getName());
    }

在这里插入图片描述

getClass()

public static void main(String[] args) {

        UserDaoImpl userDao = new UserDaoImpl();
        Class iface=userDao.getClass();
        System.out.println(iface);
        System.out.println(iface.getName());
        System.out.println(iface.getSimpleName());
    }

在这里插入图片描述

getDeclaredMethods()

 public static void main(String[] args) {

        UserDao userDao=new UserDaoImpl();
        Class iface=userDao.getClass();
        Method[] declaredMethods = iface.getDeclaredMethods();
        for(Method method:declaredMethods)
        {
            System.out.println(method.getName());
            System.out.println(method.getReturnType());
            Class<?>[] parameterTypes = method.getParameterTypes();
            for(Class<?> parameterType:parameterTypes) {
                System.out.println(parameterType.getName());
                System.out.println(parameterType.getSimpleName());
            }
        }

    }

在这里插入图片描述

substring

public static void main(String[] args) {

        UserDao userDao=new UserDaoImpl();
        Class iface=userDao.getClass();
        Method[] declaredMethods = iface.getDeclaredMethods();
        String  str="abcdefa";
        System.out.println(str.lastIndexOf("a"));
        str=str.substring(0,5);
        System.out.println(str);

    }

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值