jvm-类加载机制(四) 动静态代理

package com.test.proxy.staticproxy;

import com.test.service.dto.UserDto;
import com.test.service.impl.UserServiceImpl;

/**
 * Created by xx
 * 2020/8/4.
 */
public class SaticProxyByExtend extends UserServiceImpl {

    @Override
    public UserDto findHouse(UserDto userDto) {
        System.out.printf("come find house,paramer={%s)\r\n", userDto);
        long begin = System.currentTimeMillis();
        super.findHouse(userDto);
        long end  = System.currentTimeMillis();
        System.out.printf("come find house,result={%s)\r\n",userDto);
        System.out.printf("the time of the method costs is{%d}\r\n",end-begin);
        return userDto;
    }
}
package com.test.proxy.staticproxy;

import com.test.service.UserService;
import com.test.service.dto.UserDto;

/**
 * Created by xx
 * 2020/8/4.
 */
public class SaticProxyByReference implements UserService {

    private UserService userService;

    public SaticProxyByReference(UserService userService) {
        this.userService = userService;
    }

    @Override
    public UserDto findHouse(UserDto userDto) {
        System.out.printf("come find house,paramer={%s)\r\n",userDto);
        long begin = System.currentTimeMillis();
        userService.findHouse(userDto);
        long end  = System.currentTimeMillis();
        System.out.printf("come find house,result={%s)\r\n",userDto);
        System.out.printf("the time of the method costs is{%d}\r\n",end-begin);
        return userDto;
    }
}
package com.test.proxy.dynamicproxy.cglib;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * Created by xx
 * 2020/8/4.
 */
public class CGLibProxyFactory implements MethodInterceptor {

    private Enhancer enhancer = new Enhancer();

    public <T> T getInstants(Class<T> clazz) {
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return (T) enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.printf("come find house,paramer={%s)\r\n", objects);
        long begin = System.currentTimeMillis();
        Object result = methodProxy.invokeSuper(o, objects);
        long end = System.currentTimeMillis();
        System.out.printf("come find house,result={%s)\r\n", result);
        System.out.printf("the time of the method costs is{%d}\r\n", end - begin);
        return result;
    }
}
package com.test.proxy.dynamicproxy.jdkproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created by xx
 * 2020/8/4.
 */
public class JDKProxyFactory {

    public static <T> T getInstants(T obj){
        return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.printf("come JDKProxyFactory,paramer={%s)\r\n", args);
                long begin = System.currentTimeMillis();
                Object result = method.invoke(obj, args);
                long end = System.currentTimeMillis();
                System.out.printf("leave JDKProxyFactory,result={%s)\r\n", result);
                System.out.printf("the time of the method costs is{%d}\r\n", end - begin);
                return result;
            }
        });
    }
}
package com.test.proxy.ownproxylower;

import com.test.service.UserService;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * Created by xx
 * 2020/8/4.
 */
public class SNProxy {

    private static final String CLASS_PATH = System.getProperty("user.dir") + "/" + "/src/main/java";
    private static final String PACKAGE = "com.test.proxy.ownproxylower";
    private static final String CLASS_NAME = "$Proxy0";

    //给指定类生成代理类
    public static Object getInstance(UserService userService) {

        //java代理类文件
        File proxyFile = null;
        try {
            //1.生成java文件字符串
            String src = generateJavaString();

            //2.将字符串转换成.java文件
            proxyFile = generateFile(src);

            //3.编译Java文件,生成.class文件
            compileJavaFile(proxyFile);

            //4.将.class文件加载到java虚拟机中
            Class clazz = loadClass();

            //5.通过class反射获得对象,返回对象
            Constructor constructor = clazz.getConstructor(UserService.class);
            return constructor.newInstance(userService);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } finally {
            //6.清除中间生成的.java文件 .class文件
            if (proxyFile != null) {
                proxyFile.delete();
                String javaFilePath = proxyFile.getPath();
                String classFilePath = javaFilePath.substring(0, javaFilePath.lastIndexOf(".")) + ".class";
                new File(classFilePath).delete();
            }
        }
        return null;
    }

    private static Class loadClass() throws ClassNotFoundException {
        SNClassLoader snClassLoader = new SNClassLoader(CLASS_PATH);
        return snClassLoader.loadClass(PACKAGE + "." + CLASS_NAME);
    }

    private static void compileJavaFile(File proxyFile) {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
        Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(proxyFile);
        JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, null, null, compilationUnits);
        task.call();
    }

    private static File generateFile(String src) {
        String filePath = CLASS_PATH + "/" + (PACKAGE.replaceAll("[.]", "/")) + "/" + CLASS_NAME + ".java";
        File file = new File(filePath);
        if (file.exists()) {
            file.delete();
        }
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
            fileOutputStream.write(src.getBytes());
            fileOutputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return file;
    }


    private static String generateJavaString() {
        return "package com.test.proxy.ownproxylower;\n" +
                "import com.test.service.UserService;\n" +
                "import com.test.service.dto.UserDto;\n" +
                "public class $Proxy0 implements UserService {\n" +
                "    private UserService userService;\n" +
                "    public $Proxy0(UserService userService) {\n" +
                "        this.userService = userService;\n" +
                "    }\n" +
                "    @Override\n" +
                "    public UserDto findHouse(UserDto userDto) {\n" +
                "        System.out.printf(\"come find house,paramer={%s)\\r\\n\", userDto);\n" +
                "        long begin = System.currentTimeMillis();\n" +
                "        userService.findHouse(userDto);\n" +
                "        long end = System.currentTimeMillis();\n" +
                "        System.out.printf(\"the time of the method costs is{%d}\\r\\n\", end - begin);\n" +
                "        System.out.printf(\"come find house,result={%s)\\r\\n\", userDto);\n" +
                "        return userDto;\n" +
                "    }\n" +
                "}\n";
    }


}
package com.test.proxy.ownproxylower;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * Created by xx
 * 2020/8/4.
 */
@Getter
@Setter
@AllArgsConstructor
public class SNClassLoader extends ClassLoader {

    private String classPath;

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] bytes = readClassFile(name);
        return super.defineClass(bytes, 0, bytes.length);
    }

    private byte[] readClassFile(String name) {
        String filePath = this.getClassPath() + "/" + (name.replaceAll("[.]", "/")) + ".class";
        try (FileInputStream fileInputStream = new FileInputStream(filePath);
             ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();) {
            byte[] bytes = new byte[1024];
            int count = -1;
            while (-1 != (count = fileInputStream.read(bytes))) {
                byteArrayOutputStream.write(bytes, 0, count);
            }
            return byteArrayOutputStream.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }


}
package com.test;

import com.test.proxy.dynamicproxy.cglib.CGLibProxyFactory;
import com.test.proxy.dynamicproxy.jdkproxy.JDKProxyFactory;
import com.test.proxy.ownproxyhigher.SNProxyFactory;
import com.test.proxy.ownproxylower.SNProxy;
import com.test.proxy.staticproxy.SaticProxyByExtend;
import com.test.proxy.staticproxy.SaticProxyByReference;
import com.test.service.UserService;
import com.test.service.dto.UserDto;
import com.test.service.impl.UserServiceImpl;
import org.junit.Before;
import org.junit.Test;
import sun.misc.ProxyGenerator;

import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Created by xx
 * 2020/8/4.
 */
public class TestProxy {

    //定义被代理对象
    private UserService userService;

    //查询参数
    private UserDto userDto;

    @Before
    public void setUp() {
        userService = new UserServiceImpl();
        userDto = new UserDto(null, "张辉", "仙鹤门");
    }

    /**
     * 不使用代理的调用方式
     */
    @Test
    public void test1_NoProxy() {
        userService.findHouse(userDto);
    }

    /**
     * 静态代理实现方式1::继承方式实现代理
     */
    @Test
    public void test2_staticProxyByExtend() {
        SaticProxyByExtend saticProxyByExtend = new SaticProxyByExtend();
        saticProxyByExtend.findHouse(userDto);
    }

    /**
     * 静态代理实现方式2:使用组合|聚合
     */
    @Test
    public void test3_staticProxyByReference() {
        SaticProxyByReference saticProxyByReference = new SaticProxyByReference(userService);
        saticProxyByReference.findHouse(userDto);
    }

    /**
     * 动态代理测试:jdkproxy实现
     */
    @Test
    public void test4_javaProxy() {
        UserService userServiceProxy = JDKProxyFactory.getInstants(this.userService);
        userServiceProxy.findHouse(userDto);
    }

    /**
     * 动态代理测试:cglib实现
     */
    @Test
    public void test5_cgLibProxy() {
        UserService userServiceProxy = new CGLibProxyFactory().getInstants(UserServiceImpl.class);
        userServiceProxy.findHouse(userDto);
    }


    /**
     * 自定义动态代理测试:低级版的自定义实现
     */
    @Test
    public void test6_ownProxyLower() {
        UserService userServiceProxy = (UserService) SNProxy.getInstance(this.userService);
        userServiceProxy.findHouse(new UserDto(null, "张辉", "仙鹤门"));
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值