You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by ta...@apache.org on 2017/06/26 18:13:45 UTC

[2/2] deltaspike git commit: DELTASPIKE-1274 Refactor proxy-module / improve performance

DELTASPIKE-1274 Refactor proxy-module / improve performance

Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/b4c2ed26
Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/b4c2ed26
Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/b4c2ed26

Branch: refs/heads/master
Commit: b4c2ed26341a732f475db440c1b16f6a77115617
Parents: cdb8650
Author: Thomas Andraschko <ta...@apache.org>
Authored: Mon Jun 26 20:13:35 2017 +0200
Committer: Thomas Andraschko <ta...@apache.org>
Committed: Mon Jun 26 20:13:35 2017 +0200

----------------------------------------------------------------------
 .../core/api/provider/BeanProvider.java         |  14 +-
 .../deltaspike/core/util/ReflectionUtils.java   |   8 +
 .../api/DeltaSpikeProxyContextualLifecycle.java |  89 +--
 .../proxy/api/DeltaSpikeProxyFactory.java       |  86 +--
 .../deltaspike/proxy/spi/DeltaSpikeProxy.java   |  12 +
 .../spi/DeltaSpikeProxyClassGenerator.java      |  51 ++
 .../DeltaSpikeProxyClassGeneratorHolder.java    |  63 +++
 .../proxy/spi/ProxyClassGenerator.java          |  49 --
 .../DeltaSpikeProxyInterceptorLookup.java       | 112 ++++
 .../DeltaSpikeProxyInvocationContext.java       | 125 +++++
 .../DeltaSpikeProxyInvocationHandler.java       | 131 +++++
 ...ltaSpikeProxyInvocationWrapperException.java |  31 ++
 .../util/EnableInterceptorsProxyFactory.java    |  17 +-
 .../DeltaSpikeProxyClassGeneratorHolder.xml     |  24 +
 .../main/resources/OSGI-INF/GeneratorHolder.xml |  24 -
 .../impl/AsmDeltaSpikeProxyClassGenerator.java  | 548 +++++++++++++++++++
 .../proxy/impl/AsmProxyClassGenerator.java      | 494 -----------------
 .../AbstractManualInvocationHandler.java        |  72 ---
 .../DelegateManualInvocationHandler.java        |  49 --
 .../InterceptManualInvocationHandler.java       |  56 --
 .../impl/invocation/InterceptorLookup.java      | 109 ----
 .../invocation/ManualInvocationContext.java     | 136 -----
 ...nualInvocationThrowableWrapperException.java |  31 --
 ...pike.proxy.spi.DeltaSpikeProxyClassGenerator |  96 ++++
 ...che.deltaspike.proxy.spi.ProxyClassGenerator |  96 ----
 .../AsmDeltaSpikeProxyClassGenerator.xml        |  25 +
 .../OSGI-INF/AsmProxyClassGenerator.xml         |  25 -
 .../proxy/impl/AsmProxyClassGeneratorTest.java  |   2 +-
 28 files changed, 1337 insertions(+), 1238 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/provider/BeanProvider.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/provider/BeanProvider.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/provider/BeanProvider.java
index e5674ce..7e9b05b 100644
--- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/provider/BeanProvider.java
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/provider/BeanProvider.java
@@ -398,7 +398,19 @@ public final class BeanProvider
         return getBeanDefinitions(type, optional, includeDefaultScopedBeans, beanManager);
     }
     
-    private static <T> Set<Bean<T>> getBeanDefinitions(Class<T> type,
+    /**
+     * Get a set of {@link Bean} definitions by type, regardless of qualifiers.
+     *
+     * @param type                      the type of the bean in question
+     * @param optional                  if <code>true</code> it will return an empty set if no bean could be found.
+     *                                  Otherwise it will throw an {@code IllegalStateException}
+     * @param includeDefaultScopedBeans specifies whether dependent scoped beans should be included in the result
+     * @param <T>                       target type
+     * @param beanManager               the {@link BeanManager} to use
+     *
+     * @return the resolved set of {@link Bean} definitions or an empty set if optional is true
+     */
+    public static <T> Set<Bean<T>> getBeanDefinitions(Class<T> type,
                                                        boolean optional,
                                                        boolean includeDefaultScopedBeans,
                                                        BeanManager beanManager)

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/ReflectionUtils.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/ReflectionUtils.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/ReflectionUtils.java
index baab6a5..bfbe873 100644
--- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/ReflectionUtils.java
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/ReflectionUtils.java
@@ -504,4 +504,12 @@ public abstract class ReflectionUtils
 
         return typeHash;
     }
+    
+    public static boolean hasSameSignature(Method a, Method b)
+    {
+        return a.getName().equals(b.getName())
+                && a.getReturnType().equals(b.getReturnType())
+                && Arrays.equals(a.getParameterTypes(), b.getParameterTypes());
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyContextualLifecycle.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyContextualLifecycle.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyContextualLifecycle.java
index a58e2e7..c06aeef 100644
--- a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyContextualLifecycle.java
+++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyContextualLifecycle.java
@@ -18,8 +18,8 @@
  */
 package org.apache.deltaspike.proxy.api;
 
-import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
 import java.util.Set;
 import javax.enterprise.context.Dependent;
 import javax.enterprise.context.spi.CreationalContext;
@@ -28,10 +28,11 @@ import javax.enterprise.inject.spi.Bean;
 import javax.enterprise.inject.spi.BeanManager;
 import javax.enterprise.inject.spi.InjectionTarget;
 import javax.enterprise.inject.spi.PassivationCapable;
-import org.apache.deltaspike.core.api.provider.BeanManagerProvider;
 import org.apache.deltaspike.core.api.provider.BeanProvider;
 import org.apache.deltaspike.core.util.ExceptionUtils;
 import org.apache.deltaspike.core.util.metadata.builder.ContextualLifecycle;
+import org.apache.deltaspike.proxy.spi.DeltaSpikeProxy;
+import org.apache.deltaspike.proxy.spi.invocation.DeltaSpikeProxyInvocationHandler;
 
 /**
  * {@link ContextualLifecycle} which handles a complete lifecycle of a proxy:
@@ -47,9 +48,14 @@ public class DeltaSpikeProxyContextualLifecycle<T, H extends InvocationHandler>
 {
     private final Class<T> proxyClass;
     private final Class<H> delegateInvocationHandlerClass;
+    private final Method[] delegateMethods;
     private final Class<T> targetClass;
+    private final BeanManager beanManager;
+    
+    private DeltaSpikeProxyInvocationHandler deltaSpikeProxyInvocationHandler;
     
     private InjectionTarget<T> injectionTarget;
+    private Bean<H> handlerBean;
     private CreationalContext<?> creationalContextOfDependentHandler;
 
     public DeltaSpikeProxyContextualLifecycle(Class<T> targetClass,
@@ -60,7 +66,9 @@ public class DeltaSpikeProxyContextualLifecycle<T, H extends InvocationHandler>
         this.targetClass = targetClass;
         this.delegateInvocationHandlerClass = delegateInvocationHandlerClass;
         this.proxyClass = proxyFactory.getProxyClass(beanManager, targetClass);
-
+        this.delegateMethods = proxyFactory.getDelegateMethods(targetClass);
+        this.beanManager = beanManager;
+        
         if (!targetClass.isInterface())
         {
             AnnotatedType<T> annotatedType = beanManager.createAnnotatedType(this.targetClass);
@@ -70,20 +78,22 @@ public class DeltaSpikeProxyContextualLifecycle<T, H extends InvocationHandler>
 
     @Override
     public T create(Bean bean, CreationalContext creationalContext)
-    {
+    {        
         try
         {
-            T instance;
+            lazyInit();
+            
+            T instance = proxyClass.newInstance();
 
-            if (delegateInvocationHandlerClass == null)
-            {
-                instance = proxyClass.newInstance();
-            }
-            else
+            DeltaSpikeProxy deltaSpikeProxy = ((DeltaSpikeProxy) instance);
+            deltaSpikeProxy.setInvocationHandler(deltaSpikeProxyInvocationHandler);
+
+            // optional 
+            if (delegateInvocationHandlerClass != null)
             {
                 H delegateInvocationHandler = instantiateDelegateInvocationHandler();
-                Constructor<T> constructor = proxyClass.getConstructor(InvocationHandler.class);
-                instance = constructor.newInstance(delegateInvocationHandler);
+                deltaSpikeProxy.setDelegateInvocationHandler(delegateInvocationHandler);
+                deltaSpikeProxy.setDelegateMethods(delegateMethods);
             }
 
             if (this.injectionTarget != null)
@@ -119,34 +129,49 @@ public class DeltaSpikeProxyContextualLifecycle<T, H extends InvocationHandler>
         creationalContext.release();
     }
     
-    protected H instantiateDelegateInvocationHandler()
+    private void lazyInit()
     {
-        Set<Bean<H>> handlerBeans = BeanProvider.getBeanDefinitions(this.delegateInvocationHandlerClass, false, true);
-        
-        if (handlerBeans.size() != 1)
+        if (this.deltaSpikeProxyInvocationHandler == null)
         {
-            StringBuilder beanInfo = new StringBuilder();
-            for (Bean<H> bean : handlerBeans)
+            init();
+        }
+    }
+
+    private synchronized void init()
+    {
+        if (this.deltaSpikeProxyInvocationHandler == null)
+        {
+            this.deltaSpikeProxyInvocationHandler = BeanProvider.getContextualReference(
+                    beanManager, DeltaSpikeProxyInvocationHandler.class, false);
+
+            Set<Bean<H>> handlerBeans = BeanProvider.getBeanDefinitions(
+                    delegateInvocationHandlerClass, false, true, beanManager);
+            if (handlerBeans.size() != 1)
             {
-                if (beanInfo.length() != 0)
+                StringBuilder beanInfo = new StringBuilder();
+                for (Bean<H> bean : handlerBeans)
                 {
-                    beanInfo.append(", ");
-                }
-                beanInfo.append(bean);
+                    if (beanInfo.length() != 0)
+                    {
+                        beanInfo.append(", ");
+                    }
+                    beanInfo.append(bean);
 
-                if (bean instanceof PassivationCapable)
-                {
-                    beanInfo.append(" bean-id: ").append(((PassivationCapable)bean).getId());
+                    if (bean instanceof PassivationCapable)
+                    {
+                        beanInfo.append(" bean-id: ").append(((PassivationCapable) bean).getId());
+                    }
                 }
-            }
 
-            throw new IllegalStateException(handlerBeans.size() + " beans found for "
-                    + this.delegateInvocationHandlerClass + " found beans: " + beanInfo.toString());
+                throw new IllegalStateException(handlerBeans.size() + " beans found for "
+                        + delegateInvocationHandlerClass + " found beans: " + beanInfo.toString());
+            }
+            this.handlerBean = handlerBeans.iterator().next();
         }
-
-        Bean<H> handlerBean = handlerBeans.iterator().next();
-        
-        BeanManager beanManager = BeanManagerProvider.getInstance().getBeanManager();
+    }
+    
+    protected H instantiateDelegateInvocationHandler()
+    {
         CreationalContext<?> creationalContext = beanManager.createCreationalContext(handlerBean);
         
         H handlerInstance = (H) beanManager.getReference(handlerBean,

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyFactory.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyFactory.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyFactory.java
index 19a8099..dd41c83 100644
--- a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyFactory.java
+++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyFactory.java
@@ -22,7 +22,6 @@ import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 import javax.enterprise.inject.spi.BeanManager;
@@ -30,54 +29,15 @@ import javax.enterprise.inject.spi.BeanManager;
 import javax.interceptor.InterceptorBinding;
 
 import org.apache.deltaspike.core.util.ClassUtils;
-import org.apache.deltaspike.core.util.ServiceUtils;
-import org.apache.deltaspike.proxy.spi.ProxyClassGenerator;
+import org.apache.deltaspike.core.util.ReflectionUtils;
+import org.apache.deltaspike.proxy.spi.DeltaSpikeProxyClassGenerator;
+import org.apache.deltaspike.proxy.spi.DeltaSpikeProxyClassGeneratorHolder;
 
 public abstract class DeltaSpikeProxyFactory
 {
     private static final String SUPER_ACCESSOR_METHOD_SUFFIX = "$super";
-    
-    public static class GeneratorHolder
-    {
-        private static ProxyClassGenerator generator;
-
-        /**
-         * Setter invoked by OSGi Service Component Runtime.
-         *
-         * @param generator
-         *            generator service
-         */
-        public void setGenerator(ProxyClassGenerator generator)
-        {
-            GeneratorHolder.generator = generator;
-        }
-    }
 
-
-    /**
-     * Looks up a unique service implementation.
-     *
-     * @return ProxyClassGenerator service
-     */
-    private static ProxyClassGenerator lookupService()
-    {
-        if (GeneratorHolder.generator == null)
-        {
-            List<ProxyClassGenerator> proxyClassGeneratorList = ServiceUtils
-                .loadServiceImplementations(ProxyClassGenerator.class);
-
-            if (proxyClassGeneratorList.size() != 1)
-            {
-                throw new IllegalStateException(proxyClassGeneratorList.size()
-                    + " implementations of " + ProxyClassGenerator.class.getName()
-                    + " found. Expected exactly one implementation.");
-            }
-            GeneratorHolder.generator = proxyClassGeneratorList.get(0);
-        }
-        return GeneratorHolder.generator;
-    }
-
-    public <T> Class<T> resolveAlreadyDefinedProxyClass(Class<T> targetClass)
+    private <T> Class<T> resolveAlreadyDefinedProxyClass(Class<T> targetClass)
     {
         Class<T> proxyClass = ClassUtils.tryToLoadClassForName(constructProxyClassName(targetClass),
                 targetClass,
@@ -106,7 +66,7 @@ public abstract class DeltaSpikeProxyFactory
         {
             ArrayList<Method> allMethods = collectAllMethods(targetClass);
             ArrayList<Method> interceptMethods = filterInterceptMethods(targetClass, allMethods);
-            ArrayList<Method> delegateMethods = getDelegateMethods(targetClass, allMethods);
+            Method[] delegateMethods = getDelegateMethods(targetClass);
 
             // check if a interceptor is defined on class level. if not, skip interceptor methods
             if (interceptMethods != null
@@ -126,15 +86,14 @@ public abstract class DeltaSpikeProxyFactory
                 }
             }
 
-            ProxyClassGenerator proxyClassGenerator = lookupService();
+            DeltaSpikeProxyClassGenerator proxyClassGenerator = DeltaSpikeProxyClassGeneratorHolder.lookup();
 
             proxyClass = proxyClassGenerator.generateProxyClass(classLoader,
                     targetClass,
                     getProxyClassSuffix(),
                     SUPER_ACCESSOR_METHOD_SUFFIX,
                     getAdditionalInterfacesToImplement(targetClass),
-                    delegateMethods == null ? new Method[0]
-                            : delegateMethods.toArray(new Method[delegateMethods.size()]),
+                    delegateMethods,
                     interceptMethods == null ? new Method[0]
                             : interceptMethods.toArray(new Method[interceptMethods.size()]));
         }
@@ -142,7 +101,7 @@ public abstract class DeltaSpikeProxyFactory
         return proxyClass;
     }
 
-    protected boolean containsInterceptorBinding(BeanManager beanManager, Annotation[] annotations)
+    private boolean containsInterceptorBinding(BeanManager beanManager, Annotation[] annotations)
     {
         for (Annotation annotation : annotations)
         {            
@@ -169,12 +128,12 @@ public abstract class DeltaSpikeProxyFactory
         return false;
     }
         
-    protected String constructProxyClassName(Class<?> clazz)
+    private String constructProxyClassName(Class<?> clazz)
     {
         return clazz.getName() + getProxyClassSuffix();
     }
 
-    protected static String constructSuperAccessorMethodName(Method method)
+    private static String constructSuperAccessorMethodName(Method method)
     {
         return method.getName() + SUPER_ACCESSOR_METHOD_SUFFIX;
     }
@@ -197,14 +156,7 @@ public abstract class DeltaSpikeProxyFactory
         return clazz.getName().endsWith(getProxyClassSuffix());
     }
 
-    protected boolean hasSameSignature(Method a, Method b)
-    {
-        return a.getName().equals(b.getName())
-                && a.getReturnType().equals(b.getReturnType())
-                && Arrays.equals(a.getParameterTypes(), b.getParameterTypes());
-    }
-
-    protected boolean ignoreMethod(Method method, List<Method> methods)
+    private boolean ignoreMethod(Method method, List<Method> methods)
     {
         // we have no interest in generics bridge methods
         if (method.isBridge())
@@ -227,7 +179,7 @@ public abstract class DeltaSpikeProxyFactory
         // check if a method with the same signature is already available
         for (Method currentMethod : methods)
         {
-            if (hasSameSignature(currentMethod, method))
+            if (ReflectionUtils.hasSameSignature(currentMethod, method))
             {
                 return true;
             }
@@ -338,5 +290,19 @@ public abstract class DeltaSpikeProxyFactory
     protected abstract ArrayList<Method> getDelegateMethods(Class<?> targetClass, ArrayList<Method> allMethods);
     
     protected abstract String getProxyClassSuffix();
+    
+    
+    public Method[] getDelegateMethods(Class<?> targetClass)
+    {
+        ArrayList<Method> allMethods = collectAllMethods(targetClass);
+        ArrayList<Method> delegateMethods = getDelegateMethods(targetClass, allMethods);
+        
+        if (delegateMethods == null)
+        {
+            return new Method[0];
+        }
+
+        return delegateMethods.toArray(new Method[delegateMethods.size()]);
+    }
 }
 

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxy.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxy.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxy.java
index d58b87d..774ca2b 100644
--- a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxy.java
+++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxy.java
@@ -19,13 +19,25 @@
 package org.apache.deltaspike.proxy.spi;
 
 import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.deltaspike.proxy.spi.invocation.DeltaSpikeProxyInvocationHandler;
 
 /**
  * Interface which will automatically be implemented by the proxy instance.
  */
 public interface DeltaSpikeProxy
 {
+    void setInvocationHandler(DeltaSpikeProxyInvocationHandler invocationHandler);
+
+    DeltaSpikeProxyInvocationHandler getInvocationHandler();
+    
+    
     void setDelegateInvocationHandler(InvocationHandler delegateInvocationHandler);
 
     InvocationHandler getDelegateInvocationHandler();
+    
+    
+    void setDelegateMethods(Method[] methods);
+
+    Method[] getDelegateMethods();
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxyClassGenerator.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxyClassGenerator.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxyClassGenerator.java
new file mode 100644
index 0000000..cbef5df
--- /dev/null
+++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxyClassGenerator.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.deltaspike.proxy.spi;
+
+public interface DeltaSpikeProxyClassGenerator
+{
+    /**
+     * Generates a proxy class from the given source class, which also implements {@link DeltaSpikeProxy}.
+     * The proxy class will be generated in the same package as the original class
+     * and the suffix will be appended to the name of the class.
+     * 
+     * @param <T> The target class.
+     * @param classLoader The {@link ClassLoader} to be used to define the proxy class.
+     * @param targetClass The class to proxy.
+     * @param suffix The classname suffix.
+     * @param superAccessorMethodSuffix It's required to generate methods which just invokes the original method.
+     *                                  We generate them with the same name as the original method
+     *                                  and append the suffix.
+     * @param additionalInterfaces Additional interfaces which should be implemented.
+     *                             Please note that you must also pass new methods via <c>delegateMethods</c>.
+     * @param delegateMethods Methods which should be delegated to the
+     *                        {@link DeltaSpikeProxy#getDelegateInvocationHandler()}
+     *                        instead of invoking the original method.
+     * @param interceptMethods Methods which should be intercepted (to call interceptors or decorators)
+     *                         before invoking the original method.
+     * @return The generated proxy class.
+     */
+    <T> Class<T> generateProxyClass(ClassLoader classLoader,
+                                    Class<T> targetClass,
+                                    String suffix,
+                                    String superAccessorMethodSuffix,
+                                    Class<?>[] additionalInterfaces,
+                                    java.lang.reflect.Method[] delegateMethods,
+                                    java.lang.reflect.Method[] interceptMethods);
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxyClassGeneratorHolder.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxyClassGeneratorHolder.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxyClassGeneratorHolder.java
new file mode 100644
index 0000000..6f04d59
--- /dev/null
+++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxyClassGeneratorHolder.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.deltaspike.proxy.spi;
+
+import java.util.List;
+import org.apache.deltaspike.core.util.ServiceUtils;
+
+// TODO it would be great if we could just rewrite it to an AppScoped bean
+public class DeltaSpikeProxyClassGeneratorHolder
+{
+    private static DeltaSpikeProxyClassGenerator generator;
+
+    /**
+     * Setter invoked by OSGi Service Component Runtime.
+     *
+     * @param generator generator service
+     */
+    public void setGenerator(DeltaSpikeProxyClassGenerator generator)
+    {
+        this.generator = generator;
+    }
+    
+    /**
+     * Looks up a unique service implementation.
+     *
+     * @return ProxyClassGenerator service
+     */
+    public static DeltaSpikeProxyClassGenerator lookup()
+    {
+        if (generator == null)
+        {
+            List<DeltaSpikeProxyClassGenerator> proxyClassGeneratorList =
+                    ServiceUtils.loadServiceImplementations(DeltaSpikeProxyClassGenerator.class);
+
+            if (proxyClassGeneratorList.size() != 1)
+            {
+                throw new IllegalStateException(proxyClassGeneratorList.size()
+                    + " implementations of " + DeltaSpikeProxyClassGenerator.class.getName()
+                    + " found. Expected exactly one implementation.");
+            }
+
+            generator = proxyClassGeneratorList.get(0);
+        }
+
+        return generator;
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/ProxyClassGenerator.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/ProxyClassGenerator.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/ProxyClassGenerator.java
deleted file mode 100644
index cc9ffa6..0000000
--- a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/ProxyClassGenerator.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-package org.apache.deltaspike.proxy.spi;
-
-public interface ProxyClassGenerator
-{
-    /**
-     * Generates a proxy class from the given source class.
-     * The proxy class will be generated in the same package as the original class
-     * and the suffix will be appended to the name of the class.
-     * 
-     * @param <T> The target class.
-     * @param classLoader The {@link ClassLoader} to be used to define the proxy class.
-     * @param targetClass The class to proxy.
-     * @param suffix The classname suffix.
-     * @param superAccessorMethodSuffix It's required to generate methods which just invokes the original method.
-     *                                  We generate them with the same name as the original method
-     *                                  and append the suffix.
-     * @param additionalInterfaces Additional interfaces which should be implemented.
-     * @param delegateMethods Methods which should be delegated to the {@code delegateInvocationHandlerClass}
-     *                        instead of invoking the original method.
-     * @param interceptMethods Methods which should be intercepted (to call interceptors or decorators)
-     *                         before invoking the original method.
-     * @return The generated proxy class.
-     */
-    <T> Class<T> generateProxyClass(ClassLoader classLoader,
-                                    Class<T> targetClass,
-                                    String suffix,
-                                    String superAccessorMethodSuffix,
-                                    Class<?>[] additionalInterfaces,
-                                    java.lang.reflect.Method[] delegateMethods,
-                                    java.lang.reflect.Method[] interceptMethods);
-}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInterceptorLookup.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInterceptorLookup.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInterceptorLookup.java
new file mode 100644
index 0000000..58e8e1b
--- /dev/null
+++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInterceptorLookup.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.deltaspike.proxy.spi.invocation;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InterceptionType;
+import javax.enterprise.inject.spi.Interceptor;
+import javax.interceptor.InterceptorBinding;
+import org.apache.deltaspike.core.api.provider.BeanManagerProvider;
+
+/**
+ * Utility which stores the information about configured interceptors for each method.
+ */
+@ApplicationScoped
+class DeltaSpikeProxyInterceptorLookup
+{
+    private final Map<Method, List<Interceptor<?>>> cache = new HashMap<Method, List<Interceptor<?>>>();
+    
+    public List<Interceptor<?>> lookup(Object instance, Method method)
+    {
+        List<Interceptor<?>> interceptors = cache.get(method);
+        
+        if (interceptors == null)
+        {
+            interceptors = resolveInterceptors(instance, method);
+            cache.put(method, interceptors);
+        }
+        
+        return interceptors;
+    }
+    
+    private List<Interceptor<?>> resolveInterceptors(Object instance, Method method)
+    {
+        BeanManager beanManager = BeanManagerProvider.getInstance().getBeanManager();
+        
+        Annotation[] interceptorBindings = extractInterceptorBindings(beanManager, instance, method);
+        if (interceptorBindings.length > 0)
+        {
+            return beanManager.resolveInterceptors(InterceptionType.AROUND_INVOKE, interceptorBindings);
+        }
+
+        return new ArrayList<Interceptor<?>>();
+    }
+
+    private Annotation[] extractInterceptorBindings(BeanManager beanManager, Object instance, Method method)
+    {
+        ArrayList<Annotation> bindings = new ArrayList<Annotation>();
+
+        addInterceptorBindings(beanManager, bindings, instance.getClass().getDeclaredAnnotations());
+        addInterceptorBindings(beanManager, bindings, method.getDeclaredAnnotations());
+
+        return bindings.toArray(new Annotation[bindings.size()]);
+    }
+    
+    private void addInterceptorBindings(BeanManager beanManager, ArrayList<Annotation> bindings,
+            Annotation[] declaredAnnotations)
+    {
+        for (Annotation annotation : declaredAnnotations)
+        {
+            if (bindings.contains(annotation))
+            {
+                continue;
+            }
+            
+            Class<? extends Annotation> annotationType = annotation.annotationType();
+            
+            if (annotationType.isAnnotationPresent(InterceptorBinding.class))
+            {
+                bindings.add(annotation);
+            }
+            
+            if (beanManager.isStereotype(annotationType))
+            {
+                for (Annotation subAnnotation : annotationType.getDeclaredAnnotations())
+                {                    
+                    if (bindings.contains(subAnnotation))
+                    {
+                        continue;
+                    }
+
+                    if (subAnnotation.annotationType().isAnnotationPresent(InterceptorBinding.class))
+                    {
+                        bindings.add(subAnnotation);
+                    }  
+                }
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationContext.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationContext.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationContext.java
new file mode 100644
index 0000000..c99b4bb
--- /dev/null
+++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationContext.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.deltaspike.proxy.spi.invocation;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.Typed;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InterceptionType;
+import javax.enterprise.inject.spi.Interceptor;
+
+import org.apache.deltaspike.core.util.interceptor.AbstractInvocationContext;
+
+/**
+ * {@link javax.interceptor.InvocationContext} implementation to support interceptor invocation
+ * before proceed with the original method or delegation.
+ */
+@Typed
+public class DeltaSpikeProxyInvocationContext<T, H> extends AbstractInvocationContext<T>
+{
+    protected List<Interceptor<H>> interceptors;
+    protected int interceptorIndex;
+    protected DeltaSpikeProxyInvocationHandler invocationHandler;
+
+    protected BeanManager beanManager;
+
+    protected boolean proceedOriginal;
+    protected Object proceedOriginalReturnValue;
+
+    public DeltaSpikeProxyInvocationContext(DeltaSpikeProxyInvocationHandler invocationHandler,
+            BeanManager beanManager, List<Interceptor<H>> interceptors, 
+            T target, Method method, Object[] parameters, Object timer)
+    {
+        super(target, method, parameters, timer);
+
+        this.invocationHandler = invocationHandler;
+        this.interceptors = interceptors;
+        this.beanManager = beanManager;
+
+        this.interceptorIndex = 0;
+    }
+
+    @Override
+    public Object proceed() throws Exception
+    {
+        if (proceedOriginal)
+        {
+            return null;
+        }
+
+        if (interceptors.size() > interceptorIndex)
+        {
+            Interceptor<H> interceptor = null;
+            CreationalContext<H> creationalContext = null;
+            H interceptorInstance = null;
+
+            try
+            {
+                interceptor = interceptors.get(interceptorIndex++);
+                creationalContext = beanManager.createCreationalContext(interceptor);
+                interceptorInstance = interceptor.create(creationalContext);
+
+                return interceptor.intercept(InterceptionType.AROUND_INVOKE, interceptorInstance, this);
+            }
+            finally
+            {
+                if (creationalContext != null)
+                {
+                    if (interceptorInstance != null && interceptor != null)
+                    {
+                        interceptor.destroy(interceptorInstance, creationalContext);
+                    }
+
+                    creationalContext.release();
+                }
+            }
+        }
+
+
+        // workaround for OWB 1.1, otherwise we could just return the proceedOriginalReturnValue here
+        try
+        {
+            proceedOriginal = true;
+            proceedOriginalReturnValue = invocationHandler.proceed(target, method, parameters);
+        }
+        catch (Exception e)
+        {
+            throw e;
+        }
+        catch (Throwable e)
+        {
+            // wrap the Throwable here as interceptors declared only "throws Exception"
+            throw new DeltaSpikeProxyInvocationWrapperException(e);
+        }
+
+        return null;
+    }
+
+    public boolean isProceedOriginal()
+    {
+        return proceedOriginal;
+    }
+
+    public Object getProceedOriginalReturnValue()
+    {
+        return proceedOriginalReturnValue;
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationHandler.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationHandler.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationHandler.java
new file mode 100644
index 0000000..0f07cf8
--- /dev/null
+++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationHandler.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.deltaspike.proxy.spi.invocation;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.List;
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.Interceptor;
+import javax.inject.Inject;
+import org.apache.deltaspike.core.util.ReflectionUtils;
+import org.apache.deltaspike.proxy.api.DeltaSpikeProxyFactory;
+import org.apache.deltaspike.proxy.spi.DeltaSpikeProxy;
+
+/**
+ * The {@link InvocationHandler} which will be called directly by the proxy methods.
+ * For both <code>delegateMethods</code> and <code>interceptMethods</code>
+ * (See: {@link org.apache.deltaspike.proxy.spi.DeltaSpikeProxyClassGenerator}).
+ * 
+ * This {@link InvocationHandler} first executes CDI interceptors (if defined on method or class level) and
+ * after that the original method or the {@link DeltaSpikeProxy#getDelegateInvocationHandler()} will be executed,
+ * depending if the invoked method is a <code>intercept</code> or <code>delegate</code> method.
+ */
+@ApplicationScoped
+public class DeltaSpikeProxyInvocationHandler implements InvocationHandler
+{
+    @Inject
+    private BeanManager beanManager;
+    
+    @Inject
+    private DeltaSpikeProxyInterceptorLookup interceptorLookup;
+
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] parameters) throws Throwable
+    {
+        // check if interceptors are defined, otherwise just call the original logik
+        List<Interceptor<?>> interceptors = interceptorLookup.lookup(proxy, method);
+        if (interceptors != null && !interceptors.isEmpty())
+        {
+            try
+            {
+                DeltaSpikeProxyInvocationContext invocationContext = new DeltaSpikeProxyInvocationContext(
+                        this, beanManager, interceptors, proxy, method, parameters, null);
+
+                Object returnValue = invocationContext.proceed();
+
+                if (invocationContext.isProceedOriginal())
+                {
+                    return invocationContext.getProceedOriginalReturnValue();
+                }
+
+                return returnValue;
+            }
+            catch (DeltaSpikeProxyInvocationWrapperException e)
+            {
+                throw e.getCause();
+            }
+        }
+
+        return proceed(proxy, method, parameters);
+    }
+
+    /**
+     * Calls the original method or delegates to {@link DeltaSpikeProxy#getDelegateInvocationHandler()}
+     * after invoking the interceptor chain.
+     *
+     * @param proxy The current proxy instance.
+     * @param method The current invoked method.
+     * @param parameters The method parameter.
+     * @return The original value from the original method.
+     * @throws Throwable
+     */
+    protected Object proceed(Object proxy, Method method, Object[] parameters) throws Throwable
+    {
+        DeltaSpikeProxy deltaSpikeProxy = (DeltaSpikeProxy) proxy;
+
+        if (contains(deltaSpikeProxy.getDelegateMethods(), method))
+        {
+            return deltaSpikeProxy.getDelegateInvocationHandler().invoke(proxy, method, parameters);
+        }
+        else
+        {
+            try
+            {
+                Method superAccessorMethod = DeltaSpikeProxyFactory.getSuperAccessorMethod(proxy, method);
+                return superAccessorMethod.invoke(proxy, parameters);
+            }
+            catch (InvocationTargetException e)
+            {
+                // rethrow original exception
+                throw e.getCause();
+            }
+        }
+    }
+    
+    protected boolean contains(Method[] methods, Method method)
+    {
+        if (methods == null || methods.length == 0)
+        {
+            return false;
+        }
+        
+        for (Method current : methods)
+        {
+            if (ReflectionUtils.hasSameSignature(method, current))
+            {
+                return true;
+            }
+        }
+        
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationWrapperException.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationWrapperException.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationWrapperException.java
new file mode 100644
index 0000000..be2e867
--- /dev/null
+++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationWrapperException.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.deltaspike.proxy.spi.invocation;
+
+/**
+ * Wrapper exception to wrap and pass trough the original {@link Throwable} because
+ * the {@link javax.interceptor.InvocationContext#proceed()} method only declares "throws Exception".
+ */
+public class DeltaSpikeProxyInvocationWrapperException extends Exception
+{
+    public DeltaSpikeProxyInvocationWrapperException(Throwable e)
+    {
+        super(e);
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/util/EnableInterceptorsProxyFactory.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/util/EnableInterceptorsProxyFactory.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/util/EnableInterceptorsProxyFactory.java
index 5bae19b..e001a7d 100644
--- a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/util/EnableInterceptorsProxyFactory.java
+++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/util/EnableInterceptorsProxyFactory.java
@@ -19,12 +19,14 @@
 package org.apache.deltaspike.proxy.util;
 
 import java.io.Serializable;
-import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import javax.enterprise.inject.spi.BeanManager;
+import org.apache.deltaspike.core.api.provider.BeanProvider;
 import org.apache.deltaspike.proxy.api.DeltaSpikeProxyFactory;
+import org.apache.deltaspike.proxy.spi.DeltaSpikeProxy;
+import org.apache.deltaspike.proxy.spi.invocation.DeltaSpikeProxyInvocationHandler;
 
 public class EnableInterceptorsProxyFactory extends DeltaSpikeProxyFactory
 {
@@ -51,8 +53,17 @@ public class EnableInterceptorsProxyFactory extends DeltaSpikeProxyFactory
         try
         {
             // instantiate proxy
-            Constructor constructor = proxyClass.getConstructor(InvocationHandler.class);
-            return (T) constructor.newInstance(delegate);
+            T proxy = (T) proxyClass.newInstance();
+            
+            DeltaSpikeProxy deltaSpikeProxy = (DeltaSpikeProxy) proxy;
+            
+            // TODO this can be optimized by caching this in a appscoped bean
+            deltaSpikeProxy.setInvocationHandler(
+                    BeanProvider.getContextualReference(DeltaSpikeProxyInvocationHandler.class));
+            deltaSpikeProxy.setDelegateInvocationHandler(delegate);
+            deltaSpikeProxy.setDelegateMethods(INSTANCE.getDelegateMethods(obj.getClass()));
+            
+            return proxy;
         }
         catch (Exception e)
         {

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/resources/OSGI-INF/DeltaSpikeProxyClassGeneratorHolder.xml
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/resources/OSGI-INF/DeltaSpikeProxyClassGeneratorHolder.xml b/deltaspike/modules/proxy/api/src/main/resources/OSGI-INF/DeltaSpikeProxyClassGeneratorHolder.xml
new file mode 100644
index 0000000..0750ba9
--- /dev/null
+++ b/deltaspike/modules/proxy/api/src/main/resources/OSGI-INF/DeltaSpikeProxyClassGeneratorHolder.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements. See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership. The ASF licenses this file
+  ~ to you 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.
+  -->
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="DeltaSpikeProxyClassGeneratorHolder" immediate="true">
+   <implementation class="org.apache.deltaspike.proxy.spi.DeltaSpikeProxyClassGeneratorHolder"/>
+   <reference bind="setGenerator" cardinality="1..1" interface="org.apache.deltaspike.proxy.spi.DeltaSpikeProxyClassGenerator" 
+       name="Generator" policy="static" unbind="setGenerator"/>
+</scr:component>

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/resources/OSGI-INF/GeneratorHolder.xml
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/resources/OSGI-INF/GeneratorHolder.xml b/deltaspike/modules/proxy/api/src/main/resources/OSGI-INF/GeneratorHolder.xml
deleted file mode 100644
index 3b03fe6..0000000
--- a/deltaspike/modules/proxy/api/src/main/resources/OSGI-INF/GeneratorHolder.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one
-  ~ or more contributor license agreements. See the NOTICE file
-  ~ distributed with this work for additional information
-  ~ regarding copyright ownership. The ASF licenses this file
-  ~ to you 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.
-  -->
-<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="GeneratorHolder" immediate="true">
-   <implementation class="org.apache.deltaspike.proxy.api.DeltaSpikeProxyFactory$GeneratorHolder"/>
-   <reference bind="setGenerator" cardinality="1..1" interface="org.apache.deltaspike.proxy.spi.ProxyClassGenerator" 
-       name="Generator" policy="static" unbind="setGenerator"/>
-</scr:component>

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/AsmDeltaSpikeProxyClassGenerator.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/AsmDeltaSpikeProxyClassGenerator.java b/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/AsmDeltaSpikeProxyClassGenerator.java
new file mode 100644
index 0000000..188ea30
--- /dev/null
+++ b/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/AsmDeltaSpikeProxyClassGenerator.java
@@ -0,0 +1,548 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.deltaspike.proxy.impl;
+
+import org.apache.deltaspike.proxy.spi.DeltaSpikeProxy;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import javax.enterprise.inject.Typed;
+
+import org.apache.deltaspike.proxy.spi.invocation.DeltaSpikeProxyInvocationHandler;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.GeneratorAdapter;
+import org.objectweb.asm.commons.Method;
+import org.apache.deltaspike.proxy.spi.DeltaSpikeProxyClassGenerator;
+
+@Typed
+public class AsmDeltaSpikeProxyClassGenerator implements DeltaSpikeProxyClassGenerator
+{
+    private static final String FIELDNAME_INVOCATION_HANDLER = "invocationHandler";
+    private static final String FIELDNAME_DELEGATE_INVOCATION_HANDLER = "delegateInvocationHandler";
+    private static final String FIELDNAME_DELEGATE_METHODS = "delegateMethods";
+
+    private static final Type TYPE_CLASS = Type.getType(Class.class);
+    private static final Type TYPE_OBJECT = Type.getType(Object.class);
+    private static final Type TYPE_DELTA_SPIKE_PROXY_INVOCATION_HANDLER =
+            Type.getType(DeltaSpikeProxyInvocationHandler.class);
+    private static final Type TYPE_METHOD_ARRAY = Type.getType(java.lang.reflect.Method[].class);
+    private static final Type TYPE_INVOCATION_HANDLER = Type.getType(InvocationHandler.class);
+
+    @Override
+    public <T> Class<T> generateProxyClass(ClassLoader classLoader,
+            Class<T> targetClass,
+            String suffix,
+            String superAccessorMethodSuffix,
+            Class<?>[] additionalInterfaces,
+            java.lang.reflect.Method[] delegateMethods,
+            java.lang.reflect.Method[] interceptMethods)
+    {
+        String proxyName = targetClass.getName() + suffix;
+        String classFileName = proxyName.replace('.', '/');
+
+        byte[] proxyBytes = generateProxyClassBytes(targetClass,
+                classFileName, superAccessorMethodSuffix, additionalInterfaces, delegateMethods, interceptMethods);
+
+        Class<T> proxyClass = (Class<T>) loadClass(classLoader, proxyName, proxyBytes,
+                targetClass.getProtectionDomain());
+
+        return proxyClass;
+    }
+
+    private static byte[] generateProxyClassBytes(Class<?> targetClass,
+            String proxyName,
+            String superAccessorMethodSuffix,
+            Class<?>[] additionalInterfaces,
+            java.lang.reflect.Method[] delegateMethods,
+            java.lang.reflect.Method[] interceptMethods)
+    {
+        Class<?> superClass = targetClass;
+        String[] interfaces = new String[] { };
+
+        if (targetClass.isInterface())
+        {
+            superClass = Object.class;
+            interfaces = new String[] { Type.getInternalName(targetClass) };
+        }
+
+        // add DeltaSpikeProxy as interface
+        interfaces = Arrays.copyOf(interfaces, interfaces.length + 1);
+        interfaces[interfaces.length - 1] = Type.getInternalName(DeltaSpikeProxy.class);
+
+        if (additionalInterfaces != null && additionalInterfaces.length > 0)
+        {
+            interfaces = Arrays.copyOf(interfaces, interfaces.length + additionalInterfaces.length);
+            for (int i = 0; i < additionalInterfaces.length; i++)
+            {
+                interfaces[(interfaces.length - 1) + i] = Type.getInternalName(additionalInterfaces[i]);
+            }
+        }
+
+        Type superType = Type.getType(superClass);
+        Type proxyType = Type.getObjectType(proxyName);
+
+        final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+        cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, proxyType.getInternalName(), null,
+                superType.getInternalName(), interfaces);
+
+        
+        defineDefaultConstructor(cw, proxyType, superType);
+        defineDeltaSpikeProxyFields(cw);
+        defineDeltaSpikeProxyMethods(cw, proxyType);
+
+        if (delegateMethods != null)
+        {
+            for (java.lang.reflect.Method method : delegateMethods)
+            {
+                defineMethod(cw, method, proxyType);
+            }
+        }
+
+        if (interceptMethods != null)
+        {
+            for (java.lang.reflect.Method method : interceptMethods)
+            {
+                defineSuperAccessorMethod(cw, method, superType, superAccessorMethodSuffix);
+                defineMethod(cw, method, proxyType);
+            }
+        }
+
+        // copy all annotations from the source class
+        try
+        {
+            // ClassVisitor to intercept all annotation visits on the class
+            ClassVisitor cv = new ClassVisitor(Opcodes.ASM5)
+            {
+                @Override
+                public AnnotationVisitor visitAnnotation(String desc, boolean visible)
+                {
+                    return new CopyAnnotationVisitorAdapter(
+                            super.visitAnnotation(desc, visible),
+                            cw.visitAnnotation(desc, visible));
+                }
+            };
+
+            // visit class to proxy with our visitor to copy all annotations from the source class to our ClassWriter
+            String sourceClassFilename = targetClass.getName().replace('.', '/') + ".class";
+            ClassReader cr = new ClassReader(targetClass.getClassLoader().getResourceAsStream(sourceClassFilename));
+            cr.accept(cv, 0);
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException(e);
+        }
+
+        return cw.toByteArray();
+    }
+    
+    private static void defineDefaultConstructor(ClassWriter cw, Type proxyType, Type superType)
+    {
+        GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC,
+                new Method("<init>", Type.VOID_TYPE, new Type[]{ }),
+                null,
+                null,
+                cw);
+
+        mg.visitCode();
+
+        // invoke super constructor
+        mg.loadThis();
+        mg.invokeConstructor(superType, Method.getMethod("void <init> ()"));
+        mg.returnValue();
+        mg.endMethod();
+
+        mg.visitEnd();
+    }
+    
+    private static void defineDeltaSpikeProxyFields(ClassWriter cw)
+    {
+        // generates
+        // private DeltaSpikeProxyInvocationHandler invocationHandler;
+        cw.visitField(Opcodes.ACC_PRIVATE, FIELDNAME_INVOCATION_HANDLER,
+                TYPE_DELTA_SPIKE_PROXY_INVOCATION_HANDLER.getDescriptor(), null, null).visitEnd();
+        
+        // generates
+        // private MyInvocationHandler delegateInvocationHandler;
+        cw.visitField(Opcodes.ACC_PRIVATE, FIELDNAME_DELEGATE_INVOCATION_HANDLER,
+                TYPE_INVOCATION_HANDLER.getDescriptor(), null, null).visitEnd();
+        
+        // generates
+        // private Method[] delegateMethods;
+        cw.visitField(Opcodes.ACC_PRIVATE, FIELDNAME_DELEGATE_METHODS,
+                TYPE_METHOD_ARRAY.getDescriptor(), null, null).visitEnd();
+    }
+
+    private static void defineDeltaSpikeProxyMethods(ClassWriter cw, Type proxyType)
+    {
+        try
+        {
+            // implement #setInvocationHandler
+            Method asmMethod = Method.getMethod(DeltaSpikeProxy.class.getDeclaredMethod(
+                    "setInvocationHandler", DeltaSpikeProxyInvocationHandler.class));
+            GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, asmMethod, null, null, cw);
+
+            mg.visitCode();
+
+            mg.loadThis();
+            mg.loadArg(0);
+            mg.checkCast(TYPE_DELTA_SPIKE_PROXY_INVOCATION_HANDLER);
+            mg.putField(proxyType, FIELDNAME_INVOCATION_HANDLER, TYPE_DELTA_SPIKE_PROXY_INVOCATION_HANDLER);
+            mg.returnValue();
+
+            mg.visitMaxs(2, 1);
+            mg.visitEnd();
+
+
+            // implement #getInvocationHandler
+            asmMethod = Method.getMethod(DeltaSpikeProxy.class.getDeclaredMethod("getInvocationHandler"));
+            mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, asmMethod, null, null, cw);
+
+            mg.visitCode();
+
+            mg.loadThis();
+            mg.getField(proxyType, FIELDNAME_INVOCATION_HANDLER, TYPE_DELTA_SPIKE_PROXY_INVOCATION_HANDLER);
+            mg.returnValue();
+
+            mg.visitMaxs(2, 1);
+            mg.visitEnd();
+            
+            
+            
+            
+            // implement #setDelegateInvocationHandler
+            asmMethod = Method.getMethod(DeltaSpikeProxy.class.getDeclaredMethod(
+                    "setDelegateInvocationHandler", InvocationHandler.class));
+            mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, asmMethod, null, null, cw);
+
+            mg.visitCode();
+
+            mg.loadThis();
+            mg.loadArg(0);
+            mg.checkCast(TYPE_INVOCATION_HANDLER);
+            mg.putField(proxyType, FIELDNAME_DELEGATE_INVOCATION_HANDLER, TYPE_INVOCATION_HANDLER);
+            mg.returnValue();
+
+            mg.visitMaxs(2, 1);
+            mg.visitEnd();
+
+
+            // implement #getDelegateInvocationHandler
+            asmMethod = Method.getMethod(DeltaSpikeProxy.class.getDeclaredMethod("getDelegateInvocationHandler"));
+            mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, asmMethod, null, null, cw);
+
+            mg.visitCode();
+
+            mg.loadThis();
+            mg.getField(proxyType, FIELDNAME_DELEGATE_INVOCATION_HANDLER, TYPE_INVOCATION_HANDLER);
+            mg.returnValue();
+
+            mg.visitMaxs(2, 1);
+            mg.visitEnd();
+            
+            
+            
+            
+            // implement #setDelegateMethods
+            asmMethod = Method.getMethod(DeltaSpikeProxy.class.getDeclaredMethod(
+                    "setDelegateMethods", java.lang.reflect.Method[].class));
+            mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, asmMethod, null, null, cw);
+
+            mg.visitCode();
+
+            mg.loadThis();
+            mg.loadArg(0);
+            mg.checkCast(TYPE_METHOD_ARRAY);
+            mg.putField(proxyType, FIELDNAME_DELEGATE_METHODS, TYPE_METHOD_ARRAY);
+            mg.returnValue();
+
+            mg.visitMaxs(2, 1);
+            mg.visitEnd();
+
+
+            // implement #getDelegateMethods
+            asmMethod = Method.getMethod(DeltaSpikeProxy.class.getDeclaredMethod("getDelegateMethods"));
+            mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, asmMethod, null, null, cw);
+
+            mg.visitCode();
+
+            mg.loadThis();
+            mg.getField(proxyType, FIELDNAME_DELEGATE_METHODS, TYPE_METHOD_ARRAY);
+            mg.returnValue();
+
+            mg.visitMaxs(2, 1);
+            mg.visitEnd();
+        }
+        catch (NoSuchMethodException e)
+        {
+            throw new IllegalStateException("Unable to implement " + DeltaSpikeProxy.class.getName(), e);
+        }
+    }
+
+    private static void defineSuperAccessorMethod(ClassWriter cw, java.lang.reflect.Method method, Type superType,
+            String superAccessorMethodSuffix) 
+    {
+        Method originalAsmMethod = Method.getMethod(method);
+        Method newAsmMethod = new Method(method.getName() + superAccessorMethodSuffix,
+                originalAsmMethod.getReturnType(),
+                originalAsmMethod.getArgumentTypes());
+        GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, newAsmMethod, null, null, cw);
+        
+        mg.visitCode();
+        
+        // call super method
+        mg.loadThis();
+        mg.loadArgs();
+        mg.visitMethodInsn(Opcodes.INVOKESPECIAL,
+                superType.getInternalName(),
+                method.getName(),
+                Type.getMethodDescriptor(method),
+                false);
+        mg.returnValue();
+        
+        // finish the method
+        mg.endMethod();
+        mg.visitMaxs(10, 10);
+        mg.visitEnd();
+    }
+    
+    private static void defineMethod(ClassWriter cw, java.lang.reflect.Method method, Type proxyType)
+    {
+        Type methodType = Type.getType(method);
+        
+        ArrayList<Type> exceptionsToCatch = new ArrayList<Type>();
+        for (Class<?> exception : method.getExceptionTypes())
+        {
+            if (!RuntimeException.class.isAssignableFrom(exception))
+            {
+                exceptionsToCatch.add(Type.getType(exception));
+            }
+        }
+        
+        // push the method definition
+        int modifiers = (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED) & method.getModifiers();
+        Method asmMethod = Method.getMethod(method);
+        GeneratorAdapter mg = new GeneratorAdapter(modifiers,
+                asmMethod,
+                null,
+                getTypes(method.getExceptionTypes()),
+                cw);
+
+        // copy annotations
+        for (Annotation annotation : method.getDeclaredAnnotations())
+        {
+            mg.visitAnnotation(Type.getDescriptor(annotation.annotationType()), true).visitEnd();
+        }
+
+        mg.visitCode();
+
+        Label tryBlockStart = mg.mark();
+
+        mg.loadThis();
+        mg.getField(proxyType, FIELDNAME_INVOCATION_HANDLER, TYPE_DELTA_SPIKE_PROXY_INVOCATION_HANDLER);
+        mg.loadThis();
+        loadCurrentMethod(mg, method, methodType);
+        loadArguments(mg, method, methodType);
+        
+        mg.invokeVirtual(TYPE_DELTA_SPIKE_PROXY_INVOCATION_HANDLER,
+                Method.getMethod("Object invoke(Object, java.lang.reflect.Method, Object[])"));
+
+        // cast the result
+        mg.unbox(methodType.getReturnType());
+
+        // build try catch
+        Label tryBlockEnd = mg.mark();
+        
+        // push return
+        mg.returnValue();
+
+        // catch runtime exceptions and rethrow it
+        Label rethrow = mg.mark();
+        mg.visitVarInsn(Opcodes.ASTORE, 1);
+        mg.visitVarInsn(Opcodes.ALOAD, 1);
+        mg.throwException();
+        mg.visitTryCatchBlock(tryBlockStart, tryBlockEnd, rethrow, Type.getInternalName(RuntimeException.class));
+
+        // catch checked exceptions and rethrow it
+        boolean throwableCatched = false;
+        if (!exceptionsToCatch.isEmpty())
+        {
+            rethrow = mg.mark();
+            mg.visitVarInsn(Opcodes.ASTORE, 1);
+            mg.visitVarInsn(Opcodes.ALOAD, 1);
+            mg.throwException();
+
+            // catch declared exceptions and rethrow it...
+            for (Type exceptionType : exceptionsToCatch)
+            {
+                if (exceptionType.getClassName().equals(Throwable.class.getName()))
+                {
+                    throwableCatched = true;
+                }
+                mg.visitTryCatchBlock(tryBlockStart, tryBlockEnd, rethrow, exceptionType.getInternalName());
+            }
+        }
+
+        // if throwable isn't alreached cachted, catch it and wrap it with an UndeclaredThrowableException and throw it
+        if (!throwableCatched)
+        {
+            Type uteType = Type.getType(UndeclaredThrowableException.class);
+            Label wrapAndRethrow = mg.mark();
+
+            mg.visitVarInsn(Opcodes.ASTORE, 1);
+            mg.newInstance(uteType);
+            mg.dup();
+            mg.visitVarInsn(Opcodes.ALOAD, 1);
+            mg.invokeConstructor(uteType,
+                    Method.getMethod("void <init>(java.lang.Throwable)"));
+            mg.throwException();
+
+            mg.visitTryCatchBlock(tryBlockStart, tryBlockEnd, wrapAndRethrow, Type.getInternalName(Throwable.class));
+        }
+
+        // finish the method
+        mg.endMethod();
+        mg.visitMaxs(12, 12);
+        mg.visitEnd();
+    }
+
+    /**
+     * Generates:
+     * <pre>
+     * Method method =
+     *      method.getDeclaringClass().getMethod("methodName", new Class[] { args... });
+     * </pre>
+     * @param mg
+     * @param method
+     * @param methodType
+     */
+    private static void loadCurrentMethod(GeneratorAdapter mg, java.lang.reflect.Method method, Type methodType)
+    {
+        mg.push(Type.getType(method.getDeclaringClass()));
+        mg.push(method.getName());
+
+        // create the Class[]
+        mg.push(methodType.getArgumentTypes().length);
+        mg.newArray(TYPE_CLASS);
+
+        // push parameters into array
+        for (int i = 0; i < methodType.getArgumentTypes().length; i++)
+        {
+            // keep copy of array on stack
+            mg.dup();
+
+            // push index onto stack
+            mg.push(i);
+            mg.push(methodType.getArgumentTypes()[i]);
+            mg.arrayStore(TYPE_CLASS);
+        }
+
+        // invoke getMethod() with the method name and the array of types
+        mg.invokeVirtual(TYPE_CLASS, Method.getMethod("java.lang.reflect.Method getDeclaredMethod(String, Class[])"));
+    }
+
+    /**
+     * Defines a new Object[] and push all method argmuments into the array.
+     *
+     * @param mg
+     * @param method
+     * @param methodType
+     */
+    private static void loadArguments(GeneratorAdapter mg, java.lang.reflect.Method method, Type methodType)
+    {
+        // create the Object[]
+        mg.push(methodType.getArgumentTypes().length);
+        mg.newArray(TYPE_OBJECT);
+
+        // push parameters into array
+        for (int i = 0; i < methodType.getArgumentTypes().length; i++)
+        {
+            // keep copy of array on stack
+            mg.dup();
+
+            // push index onto stack
+            mg.push(i);
+
+            mg.loadArg(i);
+            mg.valueOf(methodType.getArgumentTypes()[i]);
+            mg.arrayStore(TYPE_OBJECT);
+        }
+    }
+
+    private static Type[] getTypes(Class<?>... src)
+    {
+        Type[] result = new Type[src.length];
+        for (int i = 0; i < result.length; i++)
+        {
+            result[i] = Type.getType(src[i]);
+        }
+        return result;
+    }
+
+    /**
+     * Adapted from http://asm.ow2.org/doc/faq.html#Q5
+     *
+     * @param b
+     *
+     * @return Class<?>
+     */
+    private static Class<?> loadClass(ClassLoader loader, String className, byte[] b,
+            ProtectionDomain protectionDomain)
+    {
+        // override classDefine (as it is protected) and define the class.
+        try
+        {
+            java.lang.reflect.Method method = ClassLoader.class.getDeclaredMethod(
+                    "defineClass", String.class, byte[].class, int.class, int.class, ProtectionDomain.class);
+
+            // protected method invocation
+            boolean accessible = method.isAccessible();
+            if (!accessible)
+            {
+                method.setAccessible(true);
+            }
+            try
+            {
+                return (Class<?>) method.invoke(loader, className, b, Integer.valueOf(0), Integer.valueOf(b.length),
+                        protectionDomain);
+            }
+            finally
+            {
+                if (!accessible)
+                {
+                    method.setAccessible(false);
+                }
+            }
+        }
+        catch (Exception e)
+        {
+            throw e instanceof RuntimeException ? ((RuntimeException) e) : new RuntimeException(e);
+        }
+    }
+}