⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 proxyfactory.java

📁 Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京技术学院的数学和计算机科学系的 Shigeru Chiba 所创建的。它已加入了开放源代码JBoss 应用服务器项目,通过使
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/* * Javassist, a Java-bytecode translator toolkit. * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved. * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License.  Alternatively, the contents of this file may be used under * the terms of the GNU Lesser General Public License Version 2.1 or later. * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. */package javassist.util.proxy;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.lang.reflect.Constructor;import java.lang.reflect.Member;import java.lang.reflect.Modifier;import java.security.ProtectionDomain;import java.util.HashMap;import java.util.WeakHashMap;import java.util.Iterator;import java.util.Map;import java.util.Set;import java.lang.ref.WeakReference;import javassist.CannotCompileException;import javassist.bytecode.*;/* * This class is implemented only with the lower-level API of Javassist. * This design decision is for maximizing performance. *//** * Factory of dynamic proxy classes. * * <p>This factory generates a class that extends the given super class and implements * the given interfaces.  The calls of the methods inherited from the super class are * forwarded and then <code>invoke()</code> is called on the method handler * associated with the generated class.  The calls of the methods from the interfaces * are also forwarded to the method handler. * * <p>For example, if the following code is executed, *  * <ul><pre> * ProxyFactory f = new ProxyFactory(); * f.setSuperclass(Foo.class); * MethodHandler mi = new MethodHandler() { *     public Object invoke(Object self, Method m, Method proceed, *                          Object[] args) throws Throwable { *         System.out.println("Name: " + m.getName()); *         return proceed.invoke(self, args);  // execute the original method. *     } * }; * f.setFilter(new MethodFilter() { *     public boolean isHandled(Method m) { *         // ignore finalize() *         return !m.getName().equals("finalize"); *     } * }); * Class c = f.createClass(); * Foo foo = (Foo)c.newInstance(); * ((ProxyObject)foo).setHandler(mi); * </pre></ul> * * <p>Then, the following method call will be forwarded to MethodHandler * <code>mi</code> and prints a message before executing the originally called method * <code>bar()</code> in <code>Foo</code>. * * <ul><pre> * foo.bar(); * </pre></ul> * * <p>The last three lines of the code shown above can be replaced with a call to * the helper method <code>create</code>, which generates a proxy class, instantiates * it, and sets the method handler of the instance: * * <ul><pre> *     : * Foo foo = (Foo)f.create(new Class[0], new Object[0], mi); * </pre></ul> * * <p>To change the method handler during runtime, * execute the following code: * * <ul><pre> * MethodHandler mi2 = ... ;    // another handler * ((ProxyObject)foo).setHandler(mi2); * </pre></ul> * * <p>You can also specify the default method handler: * * <ul><pre> * ProxyFactory f2 = new ProxyFactory(); * f2.setSuperclass(Foo.class); * f2.setHandler(mi);            // set the default handler * Class c2 = f2.createClass(); * </pre></ul> * * <p>The default handler is implicitly attached to an instance of the generated class * <code>c2</code>.   Calling <code>setHandler</code> on the instance is not necessary * unless another method handler must be attached to the instance.  * * <p>The following code is an example of method handler.  It does not execute * anything except invoking the original method: * * <ul><pre> * class SimpleHandler implements MethodHandler { *     public Object invoke(Object self, Method m, *                          Method proceed, Object[] args) throws Exception { *         return proceed.invoke(self, args); *     } * } * </pre></ul> * * <p>A proxy object generated by <code>ProxyFactory</code> is serializable * if its super class or interfaces implement a <code>java.io.Serializable</code>. * However, a serialized proxy object will not be compatible with future releases. * The serialization support should be used for short-term storage or RMI. * * @see MethodHandler * @since 3.1 */public class ProxyFactory {    private Class superClass;    private Class[] interfaces;    private MethodFilter methodFilter;    private MethodHandler handler;    private Class thisClass;    /**     * If the value of this variable is not null, the class file of     * the generated proxy class is written under the directory specified     * by this variable.  For example, if the value is      * <code>"."</code>, then the class file is written under the current     * directory.  This method is for debugging.     *     * <p>The default value is null.     */    public String writeDirectory;    private static final Class OBJECT_TYPE = Object.class;    private static final String HOLDER = "_methods_";    private static final String HOLDER_TYPE = "[Ljava/lang/reflect/Method;";    private static final String METHOD_FILTER_FIELD = "_method_filter";    private static final String HANDLER = "handler";    private static final String NULL_INTERCEPTOR_HOLDER = "javassist.util.proxy.RuntimeSupport";    private static final String DEFAULT_INTERCEPTOR = "default_interceptor";    private static final String HANDLER_TYPE        = 'L' + MethodHandler.class.getName().replace('.', '/') + ';';    private static final String HANDLER_SETTER = "setHandler";    private static final String HANDLER_SETTER_TYPE = "(" + HANDLER_TYPE + ")V";    /**     * If true, a generated proxy class is cached and it will be reused     * when generating the proxy class with the same properties is requested.     * The default value is true.     *     * @since 3.4     */    public static boolean useCache = true;     private static WeakHashMap proxyCache = new WeakHashMap();    static class CacheKey {        String classes;        MethodFilter filter;        private int hash;        WeakReference proxyClass;        MethodHandler handler;        public CacheKey(Class superClass, Class[] interfaces,                        MethodFilter f, MethodHandler h)        {            classes = getKey(superClass, interfaces);            hash = classes.hashCode();            filter = f;            handler = h;            proxyClass = null;        }        public int hashCode() { return hash; }        public boolean equals(Object obj) {            if (obj instanceof CacheKey) {                CacheKey target = (CacheKey)obj;                return target.filter == filter && target.handler == handler                       && target.classes.equals(classes);            }            else                return false;        }        static String getKey(Class superClass, Class[] interfaces) {            StringBuffer sbuf = new StringBuffer();            if (superClass != null)                sbuf.append(superClass.getName());            sbuf.append(':');            if (interfaces != null) {                int len = interfaces.length;                for (int i = 0; i < len; i++)                    sbuf.append(interfaces[i].getName()).append(',');            }            return sbuf.toString();        }    }    /**     * Constructs a factory of proxy class.     */    public ProxyFactory() {        superClass = null;        interfaces = null;        methodFilter = null;        handler = null;        thisClass = null;        writeDirectory = null;    }    /**     * Sets the super class of a proxy class.     */    public void setSuperclass(Class clazz) {        superClass = clazz;    }    /**     * Obtains the super class set by <code>setSuperclass()</code>.     *     * @since 3.4     */    public Class getSuperclass() { return superClass; }    /**     * Sets the interfaces of a proxy class.     */    public void setInterfaces(Class[] ifs) {        interfaces = ifs;    }    /**     * Obtains the interfaces set by <code>setInterfaces</code>.     *     * @since 3.4     */    public Class[] getInterfaces() { return interfaces; }    /**     * Sets a filter that selects the methods that will be controlled by a handler.     */    public void setFilter(MethodFilter mf) {        methodFilter = mf;    }    /**     * Generates a proxy class.     */    public Class createClass() {        if (thisClass == null) {            ClassLoader cl = getClassLoader();            synchronized (proxyCache) {                if (useCache)                    createClass2(cl);                else                     createClass3(cl);            }        }        return thisClass;    }    private void createClass2(ClassLoader cl) {        CacheKey key = new CacheKey(superClass, interfaces, methodFilter, handler);        /*         * Excessive concurrency causes a large memory footprint and slows the         * execution speed down (with JDK 1.5).  Thus, we use a jumbo lock for         * reducing concrrency.         */        // synchronized (proxyCache) {            HashMap cacheForTheLoader = (HashMap)proxyCache.get(cl);            if (cacheForTheLoader == null) {                cacheForTheLoader = new HashMap();                proxyCache.put(cl, cacheForTheLoader);                cacheForTheLoader.put(key, key);            }            else {                CacheKey found = (CacheKey)cacheForTheLoader.get(key);                if (found == null)                    cacheForTheLoader.put(key, key);                else {                    key = found;                    Class c = isValidEntry(key);    // no need to synchronize                    if (c != null) {                        thisClass = c;                        return;                    }                }            }        // }        // synchronized (key) {            Class c = isValidEntry(key);            if (c == null) {                createClass3(cl);                key.proxyClass = new WeakReference(thisClass);            }            else                thisClass = c;         // }    }    private Class isValidEntry(CacheKey key) {        WeakReference ref = key.proxyClass;        if (ref != null) {            Class c = (Class)ref.get();            if(c != null)                return c;        }        return null;    }    private void createClass3(ClassLoader cl) {        try {            ClassFile cf = make();            if (writeDirectory != null)                FactoryHelper.writeFile(cf, writeDirectory);            thisClass = FactoryHelper.toClass(cf, cl, getDomain());            setField(DEFAULT_INTERCEPTOR, handler);            setField(METHOD_FILTER_FIELD, methodFilter);        }        catch (CannotCompileException e) {            throw new RuntimeException(e.getMessage(), e);        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -