设计模式——代理模式

简介

1、定义

为其他对象提供一种代理以控制对这个对象对访问。

2、特点

代理模式关注于对目标方法的控制。代理者拥有控制权限,可以决定目标方法是否调用。

实现方式

1、静态代理

public interface ISubject {
    void doSomeThing();
}
public class SubjectImpl implements ISubject {

    public void doSomeThing() {
        System.out.println("do some thing...");
    }
}
public class SubjectProxy implements ISubject {

    private ISubject target;

    public SubjectProxy(ISubject target) {
        this.target = target;
    }

    public void doSomeThing() {
        System.out.println("before....");
        target.doSomeThing();
        System.out.println("after....");
    }
}

2、动态代理

2.1 JDK动态代理

public interface ISubject {
    void doSomeThing();
}
public class SubjectImpl implements ISubject {

    public void doSomeThing() {
        System.out.println("do some thing...");
    }
}
public class SubjectJdkProxy implements InvocationHandler {

    private ISubject target;

    public Object getProxyInstance(ISubject target) {
        this.target = target;
        Class<? extends ISubject> clazz = target.getClass();
        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before...");
        method.invoke(target, args);
        System.out.println("after...");
        return null;
    }
}

2.2 CGLIB(Code Generation Library)

public class SubjectImpl {
    void doSomething() {
        System.out.println("do some thing...");
    }
}
public class SubjectCglibProxy implements MethodInterceptor{

    public Object getInstance(Class clazz) throws Exception {
        Enhancer enhancer = new Enhancer();
        // 告诉cglib,生成的子类需要继承哪个类
        enhancer.setSuperclass(clazz);

        // 设置回调
        enhancer.setCallback(this);

        // 生成源码,编译成class,加载到JVM中,并返回代理对象
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("before...");
        methodProxy.invokeSuper(o, objects);
        System.out.println("after...");
        return null;
    }
public class MyTest {
    public static void main(String[] args) throws Exception {

        SubjectImpl cglibProxy = (SubjectImpl) new SubjectCglibProxy().getInstance(new SubjectImpl().getClass());
        cglibProxy.doSomething();
    }
}

手写JDK动态代理

自定义ClassLoader

public class MyClassLoader extends ClassLoader{

    private File dirPath;

    public MyClassLoader(){
        String basePath = MyClassLoader.getSystemResource("").getPath();
        this.dirPath = new File(basePath);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String className = MyClassLoader.class.getPackage().getName()+"."+name;

        if (dirPath != null) {
            File classFile = new File(dirPath, className.replaceAll("\\.", "/")+".class");
            if (classFile.exists()) {
                FileInputStream fileInputStream = null;
                ByteOutputStream outputStream = null;
                try {
                    fileInputStream = new FileInputStream(classFile);
                    outputStream = new ByteOutputStream();
                    byte[] buffer = new byte[1024];
                    int len;
                    while ((len = fileInputStream.read(buffer)) != -1){
                        outputStream.write(buffer, 0, len);
                    }
                    return defineClass(className, outputStream.getBytes(), 0, outputStream.size());
                }catch (Exception e) {

                }finally {
                    if (fileInputStream != null){
                        try {
                            fileInputStream.close();
                        }catch (Exception e) {

                        }
                    }
                    try {
                        if (outputStream != null) {
                            outputStream.close();
                        }
                    }catch (Exception e){

                    }
                   // classFile.delete();
                }
            }
        }
        return null;
    }
}

自定义InvocationHandler

public interface MyInvocationHandler {

    Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

自定义Proxy类

public class MyProxy {

    public static Object newProxyInstance(MyClassLoader classLoader,
                                          Class<?>[] interfaces,
                                          MyInvocationHandler h){
        try{
            // 1、生成源代码
            String proxySrc = generateSrc(interfaces[0]);

            // 2、将生成的源代码输出到磁盘,保存为.java文件
            String filePath = MyProxy.class.getResource("").getPath();
            File proxyFile = new File(filePath, "$Proxy0.java");
            FileWriter fileWriter = new FileWriter(proxyFile);
            fileWriter.write(proxySrc);
            fileWriter.flush();
            fileWriter.close();


            // 3、编译源代码,并且生成c.class文件
            JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager manager = javaCompiler.getStandardFileManager(null, null, null);
            Iterable iterable = manager.getJavaFileObjects(proxyFile);
            JavaCompiler.CompilationTask task = javaCompiler.getTask(null, manager,null,  null, null, iterable);
            task.call();
            manager.close();
            // 4、将class加载到JVM
            Class proxyClass = classLoader.findClass("$Proxy0");
            // 5、返回代理对象
            Constructor constructor = proxyClass.getConstructor(MyInvocationHandler.class);

            return constructor.newInstance(h);

        }catch (Exception e){
            System.out.println();
        }
        return null;

    }

    private static String generateSrc(Class<?> interfaces) {
        String enter = "\r\n";
        StringBuffer sb = new StringBuffer();
        sb.append("package cn.xiaoyanol.learn.design.pattern.proxy.myjdk;"+enter);
        sb.append("import java.lang.reflect.Method;"+ enter);
        sb.append("public class $Proxy0 implements " + interfaces.getName() + "{" + enter);

        sb.append("MyInvocationHandler h;"+ enter);

        sb.append("public $Proxy0(MyInvocationHandler h) {" + enter);
        sb.append("this.h = h;" + enter);
        sb.append("}" + enter);

        for (Method m : interfaces.getMethods()) {
            sb.append("public " + m.getReturnType().getName() + " " + m.getName() + "(){" + enter);

            sb.append("try{" + enter);
            sb.append("Method m = " + interfaces.getName() + ".class.getMethod(\"" + m.getName() + "\",new Class[]{});" + enter);
            sb.append("this.h.invoke(this,m,null);" + enter);
            sb.append("}catch(Throwable e){e.printStackTrace();}" + enter);
            sb.append("}" + enter);
        }

        sb.append("}");
        return sb.toString();
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值