代理模式精讲(手写JDK动态代理)

2018-10-10 08:39:41来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

代理模式是一种架构型模式,表现出来就是一个类代表另一个类的功能,一般用在想对访问一个类的时候做一些控制,同时又不想影响正常的业务,这种代理模式在现实的生活中应用的也非常的广泛,我用穷举法给举几个好理解的例子:

1.像我们在大城市里的中介找房子的网站,房东、租户、中间商的三角关系,就是典型的代理模式。

2.还有就是帮助人找媳妇的媒婆,也是代理模式。

3.还有黄牛党等等还有很多。

正向代理和反向代理的区别:

1.正向代理代理的是用户,用户->代理服务器->谷歌的原网站模式,通过代理服务器访问谷歌。

2.反向代理代理的是服务器,比如我们访问百度的时候,其实感觉像访问一台电脑,其实在后面有成千上万台的服务器,比如通过代理服务器代理后台的服务器进行分发请求。

下面咱们通过代码进行一步一步的进行演进:

静态代理

父亲给儿子找对象,从代码不灵活进行演变。

package pattern.proxy;
/**
 * 父亲给儿子找对象,父亲有儿子的引用
 * 才可以给儿子找对象
 */
public class Father {
    private Son person;
    public Father(Son person){
       this.person=person;
    }
    public void findLove(){
        System.out.println("根据你的要求物色");
        this.person.findLove();
        System.out.println("双色父母是不是同意");
    }
}
package pattern.proxy;
public class Son {
    public void findLove(){
        System.out.println("找对象,腿长的,漂亮的");
    }
}
package pattern.proxy;
public class ProxyTest {
    public static void main(String[] args) {
        //父亲给儿子找对象
        Father father=new Father(new Son());
        father.findLove();
    }
}

下面使用接口进行改造:

package pattern.proxy;
public interface Person {
    public void findLove();
    public void findHouse();
}
package pattern.proxy;
/**
 * 父亲给儿子找对象,父亲有儿子的引用
 * 才可以给儿子找对象
 */
public class Father implements Person {
    private Person person;
    public Father(Person person){
       this.person=person;
    }
    public void findLove(){
        System.out.println("根据你的要求物色");
        person.findLove();
        System.out.println("双色父母是不是同意");
    }
    @Override
    public void findHouse() {
        person.findHouse();
    }
}
package pattern.proxy;
public class Son implements Person {
    public void findLove(){
        System.out.println("找对象,腿长的,漂亮的");
    }
    @Override
    public void findHouse() {
        System.out.println("找房子了");
    }
}
package pattern.proxy;
public class ProxyTest {
    public static void main(String[] args) {
        //父亲给儿子找对象
        Person father=new Father(new Son());
        father.findLove();
    }
}

其实如果接口里面代理的方法太多,是比较麻烦的,下面使用动态代理进行改造。

JDK动态代理

package pattern.proxy.jdk;
public interface Person {
    public void findLove();
}
package pattern.proxy.jdk;
public class XieMu implements Person {
    public void findLove(){
        System.out.println("xiemu要找对象了,要求比较高,漂亮,美");
    }
}
package pattern.proxy.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkMeiPo implements InvocationHandler {
    //被代理的对象
    private Person target;
    public Object getInstance(XieMu target){
        this.target=target;
         Class<?> 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("我是媒婆,我要给你找对象,现在已经拿到你的需求");
        System.out.println("开始物色");
        method.invoke(target,args);
        System.out.println("如果合适,那就办事了");
        return null;
    }
}
package pattern.proxy.jdk;
public class JdkMeiPoTest {
    public static void main(String[] args) {
       Person person=(Person) new JdkMeiPo().getInstance(new XieMu());
       person.findLove();
    }
}

这里面的JdkMeiPo持有被代理人的对象,同时实现InvocationHandler接口,还有一个Proxy.newProxyInstance()的方法用来生成一个新的对象,通过字节码重组。

cglib动态代理

cglib是面向方法就可以进行代理,但是是通过字节码重组动态生成的接口。

package pattern.proxy.cglib;
public class ZhangSan {
    public void findLove(){
        System.out.println("漂亮的美美");
    }
}
package pattern.proxy.cglib;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibMeiPo implements MethodInterceptor{
    public Object getInstance(Class<?> clazz) throws Exception{
        Enhancer enhancer=new Enhancer();
        //要把哪个设置为即将生成的新类父类
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        //业务的增强
        System.out.println("我是媒婆,我要给你找对象,现在已经拿到你的需求");
        System.out.println("开始物色");
        methodProxy.invokeSuper(o,objects);
        System.out.println("如果合适,那就办事了");
        return null;
    }
}
package pattern.proxy.cglib;
public class CglibTest {
    public static void main(String[] args) throws Exception {
         ZhangSan obj=(ZhangSan) new CglibMeiPo().getInstance(ZhangSan.class);
         obj.findLove();
    }
}

 手写JDK动态代理

把动态代理生成的代理类保存到文件里:

package pattern.proxy.jdk;
import sun.misc.ProxyGenerator;
import java.io.FileOutputStream;
public class JdkMeiPoTest {
    public static void main(String[] args) throws Exception {//原理:
        //1、拿到被代理对象的引用,并且获取到它的所有的接口,反射获取
        //2、JDK Proxy类重新生成一个新的类、同时新的类要实现被代理类所有实现的所有的接口
        //3、动态生成Java代码,把新加的业务逻辑方法由一定的逻辑代码去调用(在代码中体现)
        //4、编译新生成的Java代码.class
        //5、再重新加载到JVM中运行
        //以上这个过程就叫字节码重组
        //JDK中有个规范,只要要是$开头的一般都是自动生成的
        byte[] bytes=ProxyGenerator.generateProxyClass("$Proxy0",new Class[]{Person.class});
        FileOutputStream fos=new FileOutputStream("D://$proxy0.class");
        fos.write(bytes);
        fos.flush();
        fos.close();
    }
}

生成的$Proxy0文件:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import pattern.proxy.jdk.Person;

public final class $Proxy0 extends Proxy implements Person {
    private static Method m1;
//m3调用的是findLove(),从下面的静态快可以看出来
private static Method m3; private static Method m2; private static Method m0; public $Proxy0(InvocationHandler var1) throws { super(var1); }
//Object对象的
public final boolean equals(Object var1) throws { try { return (Boolean)super.h.invoke(this, m1, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } }
//代理类实现了Person类,重写了findLove的方法
public final void findLove() throws { try {
//$Proxy0继承了Proxy类,就可以用Proxy里的InvocationHandler里的h,这个其实就是JdkMeiPo实现的接口InvocationHander.
//调用JdkMeiPo的invoke方法,传入当先的对象和invoke中执行的findLove方法,参数为空
super.h.invoke(this, m3, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } }
//Object对象的
public final String toString() throws { try { return (String)super.h.invoke(this, m2, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } }
//Object对象的
public final int hashCode() throws { try { return (Integer)super.h.invoke(this, m0, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); m3 = Class.forName("pattern.proxy.jdk.Person").getMethod("findLove"); m2 = Class.forName("java.lang.Object").getMethod("toString"); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } } }
package java.lang.reflect;
import java.lang.ref.WeakReference;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiFunction;
import sun.misc.ProxyGenerator;
import sun.misc.VM;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.reflect.misc.ReflectUtil;
import sun.security.util.SecurityConstants;
public class Proxy implements java.io.Serializable {

    private static final long serialVersionUID = -2222568056686623797L;

    /** parameter types of a proxy class constructor */
    private static final Class<?>[] constructorParams =
        { InvocationHandler.class };

    /**
     * a cache of proxy classes
     */
    private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

    /**
     * the invocation handler for this proxy instance.
     * @serial
     */
    protected InvocationHandler h;

    /**
     * Prohibits instantiation.
     */
    private Proxy() {
    }

    protected Proxy(InvocationHandler h) {
        Objects.requireNonNull(h);
        this.h = h;
    }

    @CallerSensitive
    public static Class<?> getProxyClass(ClassLoader loader,
                                         Class<?>... interfaces)
        throws IllegalArgumentException
    {
        final Class<?>[] intfs = interfaces.clone();
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }

        return getProxyClass0(loader, intfs);
    }

    private static void checkProxyAccess(Class<?> caller,
                                         ClassLoader loader,
                                         Class<?>... interfaces)
    {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            ClassLoader ccl = caller.getClassLoader();
            if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) {
                sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
            }
            ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
        }
    }

    /**
     * Generate a proxy class.  Must call the checkProxyAccess method
     * to perform permission checks before calling this.
     */
    private static Class<?> getProxyClass0(ClassLoader loader,
                                           Class<?>... interfaces) {
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }

        // If the proxy class defined by the given loader implementing
        // the given interfaces exists, this will simply return the cached copy;
        // otherwise, it will create the proxy class via the ProxyClassFactory
        return proxyClassCache.get(loader, interfaces);
    }

    /*
     * a key used for proxy class with 0 implemented interfaces
     */
    private static final Object key0 = new Object();

    /*
     * Key1 and Key2 are optimized for the common use of dynamic proxies
     * that implement 1 or 2 interfaces.
     */

    /*
     * a key used for proxy class with 1 implemented interface
     */
    private static final class Key1 extends WeakReference<Class<?>> {
        private final int hash;

        Key1(Class<?> intf) {
            super(intf);
            this.hash = intf.hashCode();
        }

        @Override
        public int hashCode() {
            return hash;
        }

        @Override
        public boolean equals(Object obj) {
            Class<?> intf;
            return this == obj ||
                   obj != null &&
                   obj.getClass() == Key1.class &&
                   (intf = get()) != null &&
                   intf == ((Key1) obj).get();
        }
    }

    /*
     * a key used for proxy class with 2 implemented interfaces
     */
    private static final class Key2 extends WeakReference<Class<?>> {
        private final int hash;
        private final WeakReference<Class<?>> ref2;

        Key2(Class<?> intf1, Class<?> intf2) {
            super(intf1);
            hash = 31 * intf1.hashCode() + intf2.hashCode();
            ref2 = new WeakReference<Class<?>>(intf2);
        }

        @Override
        public int hashCode() {
            return hash;
        }

        @Override
        public boolean equals(Object obj) {
            Class<?> intf1, intf2;
            return this == obj ||
                   obj != null &&
                   obj.getClass() == Key2.class &&
                   (intf1 = get()) != null &&
                   intf1 == ((Key2) obj).get() &&
                   (intf2 = ref2.get()) != null &&
                   intf2 == ((Key2) obj).ref2.get();
        }
    }

    /*
     * a key used for proxy class with any number of implemented interfaces
     * (used here for 3 or more only)
     */
    private static final class KeyX {
        private final int hash;
        private final WeakReference<Class<?>>[] refs;

        @SuppressWarnings("unchecked")
        KeyX(Class<?>[] interfaces) {
            hash = Arrays.hashCode(interfaces);
            refs = (WeakReference<Class<?>>[])new WeakReference<?>[interfaces.length];
            for (int i = 0; i < interfaces.length; i++) {
                refs[i] = new WeakReference<>(interfaces[i]);
            }
        }

        @Override
        public int hashCode() {
            return hash;
        }

        @Override
        public boolean equals(Object obj) {
            return this == obj ||
                   obj != null &&
                   obj.getClass() == KeyX.class &&
                   equals(refs, ((KeyX) obj).refs);
        }

        private static boolean equals(WeakReference<Class<?>>[] refs1,
                                      WeakReference<Class<?>>[] refs2) {
            if (refs1.length != refs2.length) {
                return false;
            }
            for (int i = 0; i < refs1.length; i++) {
                Class<?> intf = refs1[i].get();
                if (intf == null || intf != refs2[i].get()) {
                    return false;
                }
            }
            return true;
        }
    }

    /**
     * A function that maps an array of interfaces to an optimal key where
     * Class objects representing interfaces are weakly referenced.
     */
    private static final class KeyFactory
        implements BiFunction<ClassLoader, Class<?>[], Object>
    {
        @Override
        public Object apply(ClassLoader classLoader, Class<?>[] interfaces) {
            switch (interfaces.length) {
                case 1: return new Key1(interfaces[0]); // the most frequent
                case 2: return new Key2(interfaces[0], interfaces[1]);
                case 0: return key0;
                default: return new KeyX(interfaces);
            }
        }
    }

    /**
     * A factory function that generates, defines and returns the proxy class given
     * the ClassLoader and array of interfaces.
     */
    private static final class ProxyClassFactory
        implements BiFunction<ClassLoader, Class<?>[], Class<?>>
    {

        private static final String proxyClassNamePrefix = "$Proxy";

        private static final AtomicLong nextUniqueNumber = new AtomicLong();

        @Override
        public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

            Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
            for (Class<?> intf : interfaces) {
                   Class<?> interfaceClass = null;
                try {
                    interfaceClass = Class.forName(intf.getName(), false, loader);
                } catch (ClassNotFoundException e) {
                }
                if (interfaceClass != intf) {
                    throw new IllegalArgumentException(
                        intf + " is not visible from class loader");
                }
                /*
                 * Verify that the Class object actually represents an
                 * interface.
                 */
                if (!interfaceClass.isInterface()) {
                    throw new IllegalArgumentException(
                        interfaceClass.getName() + " is not an interface");
                }
                /*
                 * Verify that this interface is not a duplicate.
                 */
                if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
                    throw new IllegalArgumentException(
                        "repeated interface: " + interfaceClass.getName());
                }
            }

            String proxyPkg = null;     // package to define proxy class in
            int accessFlags = Modifier.PUBLIC | Modifier.FINAL;

            /*
             * Record the package of a non-public proxy interface so that the
             * proxy class will be defined in the same package.  Verify that
             * all non-public proxy interfaces are in the same package.
             */
            for (Class<?> intf : interfaces) {
                int flags = intf.getModifiers();
                if (!Modifier.isPublic(flags)) {
                    accessFlags = Modifier.FINAL;
                    String name = intf.getName();
                    int n = name.lastIndexOf('.');
                    String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
                    if (proxyPkg == null) {
                        proxyPkg = pkg;
                    } else if (!pkg.equals(proxyPkg)) {
                        throw new IllegalArgumentException(
                            "non-public interfaces from different packages");
                    }
                }
            }

            if (proxyPkg == null) {
                // if no non-public proxy interfaces, use com.sun.proxy package
                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
            }
            long num = nextUniqueNumber.getAndIncrement();
            String proxyName = proxyPkg + proxyClassNamePrefix + num;
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, accessFlags);
            try {
                return defineClass0(loader, proxyName,
                                    proxyClassFile, 0, proxyClassFile.length);
            } catch (ClassFormatError e) {
              
                throw new IllegalArgumentException(e.toString());
            }
        }
    }

//loalder类加载器
//实现的接口数组
//h所有动态代理类的方法调用,都会交由InvocationHandler接口实现类里的invoke()方法去处理。这是动态代理的关键所在 @CallerSensitive
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { Objects.requireNonNull(h); final Class<?>[] intfs = interfaces.clone(); final SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } /* * Look up or generate the designated proxy class. */ Class<?> cl = getProxyClass0(loader, intfs); /* * Invoke its constructor with the designated invocation handler. */ try { if (sm != null) { checkNewProxyPermission(Reflection.getCallerClass(), cl); } final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (!Modifier.isPublic(cl.getModifiers())) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { cons.setAccessible(true); return null; } }); } return cons.newInstance(new Object[]{h}); } catch (IllegalAccessException|InstantiationException e) { throw new InternalError(e.toString(), e); } catch (InvocationTargetException e) { Throwable t = e.getCause(); if (t instanceof RuntimeException) { throw (RuntimeException) t; } else { throw new InternalError(t.toString(), t); } } catch (NoSuchMethodException e) { throw new InternalError(e.toString(), e); } } private static void checkNewProxyPermission(Class<?> caller, Class<?> proxyClass) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { if (ReflectUtil.isNonPublicProxyClass(proxyClass)) { ClassLoader ccl = caller.getClassLoader(); ClassLoader pcl = proxyClass.getClassLoader(); // do permission check if the caller is in a different runtime package // of the proxy class int n = proxyClass.getName().lastIndexOf('.'); String pkg = (n == -1) ? "" : proxyClass.getName().substring(0, n); n = caller.getName().lastIndexOf('.'); String callerPkg = (n == -1) ? "" : caller.getName().substring(0, n); if (pcl != ccl || !pkg.equals(callerPkg)) { sm.checkPermission(new ReflectPermission("newProxyInPackage." + pkg)); } } } } public static boolean isProxyClass(Class<?> cl) { return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl); } @CallerSensitive public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException { if (!isProxyClass(proxy.getClass())) { throw new IllegalArgumentException("not a proxy instance"); } final Proxy p = (Proxy) proxy; final InvocationHandler ih = p.h; if (System.getSecurityManager() != null) { Class<?> ihClass = ih.getClass(); Class<?> caller = Reflection.getCallerClass(); if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(), ihClass.getClassLoader())) { ReflectUtil.checkPackageAccess(ihClass); } } return ih; } private static native Class<?> defineClass0(ClassLoader loader, String name, byte[] b, int off, int len); }

下面实现一个自己的动态代理:

package pattern.proxy.custom;
public interface Person {
    public void findLove();
}
package pattern.proxy.custom;
public class XieMu implements Person {
    public void findLove(){
        System.out.println("xiemu要找对象了,要求比较高,漂亮,美");
    }
}
package pattern.proxy.custom;
import java.lang.reflect.Method;

public class CustomMeiPo implements JavaInvocationHandler {

    private Person target;

    public Object getInstance(Person target){
        this.target=target;
        Class<?> clazz=target.getClass();
        return JavaProxy.newProxyInstance(new JavaClassLoader(),clazz.getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("我是媒婆,我要给你找对象,现在已经拿到你的需求");
        System.out.println("开始物色");
        method.invoke(target,args);
        System.out.println("如果合适,那就办事了");
        return null;
    }
}

根据kdk里面的主要java类创建自定义的类:

package pattern.proxy.custom;

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Iterator;

public class JavaProxy {

    public static final String Ln="\r\n";

    public static Object newProxyInstance(JavaClassLoader classLoader,
                                          Class<?>[] interfaces,
                                          JavaInvocationHandler h){
      try {
          //1.动态生成源代码.java文件
          String src=generateSrc(interfaces);
          //2.java文件输出到磁盘
          String filePath=JavaProxy.class.getResource("").getPath();
          System.out.println(filePath);
          File file=new File(filePath+"$Proxy0.java");
          FileWriter fw=new FileWriter(file);
          fw.write(src);
          fw.flush();
          fw.close();
          //3.把生成的.java文件编译成.class文件
          JavaCompiler compiler= ToolProvider.getSystemJavaCompiler();
          StandardJavaFileManager manage=compiler.getStandardFileManager(null,null,null);
          Iterable iterable=manage.getJavaFileObjects(file);
          JavaCompiler.CompilationTask task=compiler.getTask(null,null,null,null,null,null);
          task.call();
          manage.close();
          //4.编译生成的.class文件加载到JVM中来
          Class proxyClass=classLoader.findClass("$Proxy0");
          Constructor c=proxyClass.getConstructor(JavaInvocationHandler.class);
file.delete();
//5.返回字节码重组后新的对象 return c.newInstance(h); }catch (Exception e){ e.printStackTrace(); } return null; } public static String generateSrc(Class<?>[] interfaces){ StringBuffer sb=new StringBuffer(); sb.append("package pattern.proxy.custom;" + Ln); sb.append("import java.lang.reflect.Method;"+ Ln); sb.append("public class $Proxy0 implements " + interfaces[0].getName() + "{" + Ln); sb.append("public JavaInvocationHandler h;" + Ln); sb.append("public $Proxy0(JavaInvocationHandler h) { "+Ln); sb.append("this.h=h;"+Ln); sb.append("}"+Ln); for (Method m:interfaces[0].getMethods()){ sb.append("public "+ m.getReturnType().getName() + " " +m.getName() + "(){"+ Ln); sb.append("try{"+Ln); sb.append("Method m="+interfaces[0].getName()+".class.getMethod(\"" + m.getName() + "\",new Class[]{});" + Ln); sb.append("this.h.invoke(this,m,null);"+Ln); sb.append("}catch(Throwable e){" + Ln); sb.append("e.printStackTrace();" + Ln); sb.append("}" + Ln); sb.append("}" + Ln); } sb.append("}" + Ln); return sb.toString(); } }
package pattern.proxy.custom;
import java.lang.reflect.Method;
public interface JavaInvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable;
}
package pattern.proxy.custom;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class JavaClassLoader extends ClassLoader {

    private File classPathFile;

    public JavaClassLoader(){
        String classPath=JavaClassLoader.class.getResource("").getPath();
        this.classPathFile=new File(classPath);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String className=JavaClassLoader.class.getPackage().getName()+"."+name;
        if(classPathFile!=null){
          File classFile=new File(classPathFile,name.replaceAll("\\.","/")+".class");
          if(classFile.exists()){
              FileInputStream in=null;
              ByteArrayOutputStream out=null;
              try {
                  in=new FileInputStream(classFile);
                  out=new ByteArrayOutputStream();
                  byte[] buff=new byte[1024];
                  int len;
                  while ((len=in.read(buff))!=-1){
                     out.write(buff,0,len);
                  }
                  return defineClass(className,out.toByteArray(),0,out.size());
              }catch (Exception e){
                  e.printStackTrace();
              }finally {
                  if(in!=null){
                      try {
                          in.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
                  if(out!=null){
                      try {
                          out.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
              }
          }
        }
        return null;
    }
}

测试类:

package pattern.proxy.custom;

public class CustomProxyTest {

    public static void main(String[] args) {
        Person person=(Person) new CustomMeiPo().getInstance(new XieMu());
        person.findLove();
    }
}

效果:

我是媒婆,我要给你找对象,现在已经拿到你的需求
开始物色
xiemu要找对象了,要求比较高,漂亮,美
如果合适,那就办事了

喜欢和喜欢学习的一起交流技术!

 

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:小白学线程入门(易懂)

下一篇:Oracle数据库的创建表全