Java/Reflection/Proxy

Материал из Java эксперт
Перейти к: навигация, поиск

A demonstration of a proxy factory

   <source lang="java">
 

/*

*     file: SomeClassFactory.java
*  package: oreilly.hcj.proxies
*
* This software is granted under the terms of the Common Public License,
* CPL, which may be found at the following URL:
* http://www-124.ibm.ru/developerworks/oss/CPLv1.0.htm
*
* Copyright(c) 2003-2005 by the authors indicated in the @author tags.
* All Rights are Reserved by the various authors.
*
########## DO NOT EDIT ABOVE THIS LINE ########## */

import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /**

* An invocation handler that counts the number of calls for all methods in the
* target class.
* 
* @author 
* @version $Revision: 1.2 $
*/

public class DemoCountingProxy {

 /**
  * Run the demonstration.
  * 
  * @param args
  *          Command Line Arguments (ignored).
  */
 public static final void main(final String[] args) {
   SomeClassCountingProxy proxy = SomeClassFactory.getCountingProxy();
   proxy.someMethod();
   proxy.someOtherMethod("Our Proxy works!");
   System.out.println("Method Invocation Count = " + proxy.getInvocationCount());
 }

} /* ########## End of File ########## */


 </source>
   
  
 
  



A dynamic proxy adapter which allows overriding several methods of a target proxy

   <source lang="java">

/*

* Copyright 2006-2007 The Scriptella Project Team.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /**

* A dynamic proxy adapter which allows overriding several
* methods of a target proxy.
*

To create a proxy adapter for Interface, create subclass of * ProxyAdapter and define methods from Interface you want to handle, * other methods invocations will be failed. * * @author Fyodor Kupolov * @version 1.0 */ public class ProxyAdapter<T> { private final T proxy; @SuppressWarnings("unchecked") public ProxyAdapter(Class... interfaces) { proxy = (T) Proxy.newProxyInstance(getClass().getClassLoader(), interfaces, new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Method m; try { //Determine if the method has been defined in a subclass m = ProxyAdapter.this.getClass().getMethod(method.getName(), method.getParameterTypes()); m.setAccessible(true); } catch (Exception e) { //if not found throw new UnsupportedOperationException(method.toString(), e); } //Invoke the method found and return the result try { return m.invoke(ProxyAdapter.this, args); } catch (InvocationTargetException e) { throw e.getCause(); } } }); } /** * @return proxy instance implementing T. */ public T getProxy() { return proxy; } /** * Usage example */ public static void main(String[] args) throws Exception { //Create adapter for Appendable ProxyAdapter<Appendable> pa = new ProxyAdapter(Appendable.class) { private StringBuilder sb = new StringBuilder(); //Override only 2 methods: append and toString public Appendable append(char c) { System.out.println("Proxy append(char c) method. Append "+c); sb.append(c); return (Appendable) getProxy(); } public String toString() { return "Proxy toString method: "+sb; } }; final Appendable a = pa.getProxy(); a.append("1").append("2"); System.out.println("a.toString() = " + a.toString()); //this invocation fails because no method has been created a.append("Not implemented"); } } </source>

A high-performance factory for dynamic proxy objects

   <source lang="java">

/*

* Copyright 2006 (C) TJDO.
* All rights reserved.
*
* This software is distributed under the terms of the TJDO License version 1.0.
* See the terms of the TJDO License in the documentation provided with this software.
*
* $Id: ProxyFactory.java,v 1.1 2006/08/11 20:41:59 jackknifebarber Exp $
*/

import java.lang.ref.Reference; import java.lang.ref.SoftReference; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Proxy;

/**

* A high-performance factory for dynamic proxy objects.
* <p>
* A ProxyFactory performs the same function as
* java.lang.reflect.Proxy.newProxyInstance(), but does so for a single
* set of interfaces.
* It holds a (soft) reference to the proxy class constructor and so can create
* many proxies of the same type with very little overhead.
* <p>
* The generated proxy class is assigned the same class loader as the
* ProxyFactory class itself.
*
* @author 
* @version $Revision: 1.1 $
*/

public class ProxyFactory {

   private final Class[] interfaces;
   private Reference ctorRef;
   /**
    * Creates a factory for proxy objects that implement the specified
    * interface.
    *
    * @param intfc
    *      the interface for the proxy class to implement
    */
   public ProxyFactory(Class intfc)
   {
       this(new Class[] { intfc });
   }
   /**
    * Creates a factory for proxy objects that implement the specified
    * interface(s).
    *
    * @param interfaces
    *      the list of interfaces for the proxy class to implement
    */
   public ProxyFactory(Class[] interfaces)
   {
       this.interfaces = interfaces;
   }
   /**
    * Returns an instance of a proxy class for this factory"s interfaces that
    * dispatches method invocations to the specified invocation handler. 
    * ProxyFactory.newInstance throws IllegalArgumentException
    * for the same reasons that Proxy.getProxyClass does.
    *
    * @param handler
    *      the invocation handler to dispatch method invocations to 
    * @return
    *      a proxy instance with the specified invocation handler of a proxy
    *      class that implements this factory"s specified interfaces 
    *
    * @throws IllegalArgumentException
    *      if any of the restrictions on the parameters that may be passed to
    *      getProxyClass are violated 
    * @throws NullPointerException
    *      if the invocation handler is null
    */
   public Object newInstance(InvocationHandler handler)
   {
       if (handler == null)
           throw new NullPointerException();
       try
       {
           return getConstructor().newInstance(new Object[] { handler });
       }
       catch (InstantiationException e)    { throw new InternalError(e.toString()); }
       catch (IllegalAccessException e)    { throw new InternalError(e.toString()); }
       catch (InvocationTargetException e) { throw new InternalError(e.toString()); }
   }
   private synchronized Constructor getConstructor()
   {
       Constructor ctor = ctorRef == null ? null : (Constructor)ctorRef.get();
       if (ctor == null)
       {
           try
           {
               ctor = Proxy.getProxyClass(getClass().getClassLoader(), interfaces)
                           .getConstructor(new Class[] { InvocationHandler.class });
           }
           catch (NoSuchMethodException e)
           {
               throw new InternalError(e.toString());
           }
           ctorRef = new SoftReference(ctor);
       }
       return ctor;
   }

}

 </source>
   
  
 
  



Creating a Proxy Object

   <source lang="java">
 

import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; interface MyInterface {

 void method();

} class MyInterfaceImpl implements MyInterface {

 public void method() {
   System.out.println("method");
 }

} class ProxyClass implements InvocationHandler {

 Object obj;
 public ProxyClass(Object o) {
   obj = o;
 }
 public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
   Object result = null;
   try {
     System.out.println("before the method is called ");
     result = m.invoke(obj, args);
   } catch (Exception eBj) {
   } finally {
     System.out.println("after the method is called"); 
   }
   return result;
 }

} public class Main {

 public static void main(String[] argv) throws Exception {
   MyInterface myintf = (MyInterface) Proxy.newProxyInstance(MyInterface.class.getClassLoader(),
       new Class[] { MyInterface.class }, new ProxyClass(new MyInterfaceImpl()));
   myintf.method();
 }

}


 </source>
   
  
 
  



Demonstrates a dangerous use of proxy names

   <source lang="java">
 

/*

*     file: SomeClassFactory.java
*  package: oreilly.hcj.proxies
*
* This software is granted under the terms of the Common Public License,
* CPL, which may be found at the following URL:
* http://www-124.ibm.ru/developerworks/oss/CPLv1.0.htm
*
* Copyright(c) 2003-2005 by the authors indicated in the @author tags.
* All Rights are Reserved by the various authors.
*
########## DO NOT EDIT ABOVE THIS LINE ########## */

import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /**

* An invocation handler that counts the number of calls for all methods in the
* target class.
* 
* @author 
* @version $Revision: 1.2 $
*/

public class DangerousNames {

 /** 
  * Run the demonstration.
  *
  * @param args Command line arguments (ignored).
  */
 public static final void main(final String[] args) {
   SomeClass proxy = SomeClassFactory.getDynamicSomeClassProxy();
   System.out.println(proxy.getClass().getName());
   try {
     Class cl = Class.forName("$Proxy0");  // <== Dangerous!
     System.out.println(cl.getName());
   } catch (final ClassNotFoundException ex) {
     ex.printStackTrace();
   }
 }

} /* ########## End of File ########## */


 </source>
   
  
 
  



Demonstrates the basic concept of proxies generated by clients to the proxies

   <source lang="java">
 

/*

*     file: SomeClassFactory.java
*  package: oreilly.hcj.proxies
*
* This software is granted under the terms of the Common Public License,
* CPL, which may be found at the following URL:
* http://www-124.ibm.ru/developerworks/oss/CPLv1.0.htm
*
* Copyright(c) 2003-2005 by the authors indicated in the @author tags.
* All Rights are Reserved by the various authors.
*
########## DO NOT EDIT ABOVE THIS LINE ########## */

import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /**

* An invocation handler that counts the number of calls for all methods in the
* target class.
* 
* @author 
* @version $Revision: 1.2 $
*/

public class DemoClientGeneratedProxy {

 /** 
  * Run the demonstration.
  *
  * @param args Command Line Arguments (ignored).
  */
 public static final void main(final String[] args) {
   SomeClassProxy proxy = new SomeClassProxy(new SomeClassImpl("Fred"));
   proxy.someMethod();
   proxy.someOtherMethod("Our Proxy works!");
 }

} /* ########## End of File ########## */


 </source>