天天看點

Industrial-level Dynamic Proxy(2)

/**

*    

*/

package poxy;

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

import java.util.*;

import callback.PrimitiveUtil;

* More industrial-level dynamic proxy , which main detach the Invocation handler and the real instance of a proxy class,

* which can store many proxy handler with them listener, this is very useful.

* Mean while, it also can work in multi thread env, so you can use it with Thread pool and Scheduler!

* @author daniel

*

public class IndustrialDynamicProxy {

  /*

    * container of iface & his InvocationHandler

    * Note: work in multithread env

    */

  private Map _iface2Handler = new HashMap();

    * Generates the 'caller' side of the caller/listener relationship.

  public Object generateCaller(Class iFace, CallBackType type) {

    CallBackHanlder newHandler;

    Object proxy=null;

    //check iface

    if(!iFace.isInterface()){

        throw new IllegalArgumentException("Class [" + iFace.getName() + "] is not an interface");

    }

    //generate a new handler    

    newHandler = new CallBackHanlder(type);

    //generate the face's proxy

    proxy = Proxy.newProxyInstance(iFace.getClassLoader(),

                    new Class[] { iFace },

                    newHandler);

    //register iface & proxy

    synchronized(_iface2Handler){

      if(_iface2Handler.containsKey(iFace)){

        throw new IllegalArgumentException("Caller already generated " + " for interface [" +    

                                                iFace.getName() + "]");

      }

      _iface2Handler.put(iFace, newHandler);

    return proxy;

  }

    * Register a listener for a given interface.    If the caller has not

         * been registered, then an error will be thrown.    

    public void registerListener(Class iFace, Object o) {

     CallBackHanlder handler;

     if(!iFace.isAssignableFrom(o.getClass())){

        throw new IllegalArgumentException("Object [" + o + "] does not " +

                                         "implement [" + iFace.getName() +

                                         "]");

     }

     synchronized (_iface2Handler) {

        handler = (CallBackHanlder) _iface2Handler.get(iFace);

     if(handler == null){

        throw new IllegalArgumentException("No callback for interface [" +

                                         iFace.getName() + "] exists");

     handler.addListener(o);

  /**

    * @param args

  public static void main(String[] args) {

    //Base testhandler

    IndustrialDynamicProxy    x=new IndustrialDynamicProxy();

    //register iface, get the proxy

    MyInterface caller = (MyInterface)x.generateCaller(MyInterface.class, CallBackType.RETURN_LAST);

    //register the listener(real instance)

    x.registerListener(MyInterface.class, new MyInterface(){

      @Override

      public int addTwo(int a, int b) {

        System.out.println("Target method called");

                                return a + b;

      }        

    });

    //call the listener

    int result=caller.addTwo(2, 4);

    //take a look

    System.out.println("addTwo(2,4):"+result);

    * An inner class to operate listeners in private

  static class CallBackHanlder implements InvocationHandler{

    /*

     * container of listeners (real instance)

     * Note: work in multithread env

     */

    private Set _listeners = new HashSet();

    //tool of get right Type

    private CallBackType _type = null;

    CallBackHanlder(CallBackType type){

      this._type=type;

    private void addListener(Object o){

      synchronized(_listeners){

        _listeners.add(o);

    @Override

    public Object invoke(Object proxy, Method method, Object[] args)

        throws Throwable {

      Set listeners;

      synchronized (_listeners) {

                                listeners = new HashSet(_listeners);

                        }

      return _type.callListeners(method, args, listeners);

}

//Interface

interface MyInterface {

        int addTwo(int a, int b);

/*

* CallBackType,    

abstract class CallBackType {

        public static final CallBackType RETURN_LAST = new CallBackType() {

                public Object callListeners(Method meth, Object[] methArgs,Set listeners)throws Throwable

                {

                        Object last = null;

                        for (Iterator i=listeners.iterator(); i.hasNext(); ) {

                                Object listener = (Object)i.next();

                                try {

                                        last = meth.invoke(listener, methArgs);

                                } catch(InvocationTargetException e) {

                                        throw e.getTargetException();

                                }

                        if (last == null) {

                                // Nobody listening ...

                                return PrimitiveUtil.getBasicValue(meth.getReturnType());

                        return last;

                }

        };        

        public abstract Object callListeners(Method meth, Object[] methArgs,

                                                                                 Set listeners)

                throws Throwable;

}

繼續閱讀