title: How to create dynamic proxy with Spring and Java
body: <p>I have this situation:
  I have one interface Service which aggregates all service interfaces. So for example if I have two interfaces ILoginService1 and ILoginService2 the Service interface looks like this</p>
  
  <pre><code>Service extends ILoginService1,ILoginService2. 
  </code></pre>
  
  <p>I need this interface to be accessible in a given context like this:</p>
  
  <pre><code>service.login();
  </code></pre>
  
  <p>This is my solution (something similar to <a href="http://artofsoftwarereuse.com/tag/dynamic-proxy/" rel="nofollow">http://artofsoftwarereuse.com/tag/dynamic-proxy/</a>):</p>
  
  <p>I create one annotation ServiceFacade, which I put on Service interface, then I have BeanPostProcessor in which I create DynamicProxy for the Service interface.
  But the problem is that Service interface isn't pick up from spring component scan, even in the case I put @Component on it, but other components are put in Spring container.</p>
  
  <p>How can I fix my solution so far or I'm missing something or is there other solutions?
  Here is source code:
  applicationContext.xml</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:context="http://www.springframework.org/schema/context"
         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"&gt;
  
      &lt;context:annotation-config/&gt;    
      &lt;context:component-scan base-package="org.finki.auction.ui.application"/&gt;
      &lt;context:component-scan base-package="org.finki.auction.services"/&gt;
  
  &lt;/beans&gt;
  </code></pre>
  
  <p>Annotation:</p>
  
  <pre><code>@Target(ElementType.TYPE)
  @Retention(RetentionPolicy.RUNTIME)
  public @interface ServiceFacade{}
  </code></pre>
  
  <p>Invocation Handler for Dynamic Proxy:</p>
  
  <pre><code>/**
   * 
   */
  package org.finki.auction.services;
  
  import java.lang.reflect.InvocationHandler;
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.util.HashMap;
  import java.util.Map;
  
  import org.springframework.beans.BeansException;
  import org.springframework.context.ApplicationContext;
  import org.springframework.context.ApplicationContextAware;
  import org.springframework.stereotype.Component;
  import org.springframework.stereotype.Service;
  
  /**
   * 
   */
  @Component("serviceLayer")
  public class ServiceLayer implements InvocationHandler, ApplicationContextAware
  {
  
      private static ApplicationContext applicationContext = null;
      private static Map&lt;String, String&gt; serviceMap = new HashMap&lt;&gt;();
  
      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
      {
          Object result;
          try
          {
              String searchKey = method.getName();
              String beanName = serviceMap.get(searchKey);
              Object methodObject = applicationContext.getBean(beanName);
              result = method.invoke(methodObject, args);
          } catch (InvocationTargetException e)
          {
              throw e.getTargetException();
          } catch (Exception e)
          {
              throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
          }
          return result;
      }
  
      @Override
      public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
      {
          ServiceLayer.applicationContext = applicationContext;
  
          Map&lt;String, Object&gt; beans = applicationContext.getBeansWithAnnotation(Service.class);
          for (Map.Entry&lt;String, Object&gt; entryBean : beans.entrySet())
          {
              String beanName = entryBean.getKey();
              Object beanObject = entryBean.getValue();
              Method[] beanMethods = beanObject.getClass().getDeclaredMethods();
              for (Method bMethod : beanMethods)
              {
                  serviceMap.put(bMethod.getName(), beanName);
              }
          }
      }
  
  }
  </code></pre>
  
  <p>BeanPostProcessor class:</p>
  
  <pre><code>/**
   * 
   */
  package org.finki.auction.services.annotation;
  
  import java.lang.reflect.Proxy;
  import java.util.Arrays;
  
  import org.finki.auction.services.Service;
  import org.finki.auction.services.ServiceLayer;
  import org.springframework.beans.BeansException;
  import org.springframework.beans.factory.config.BeanPostProcessor;
  import org.springframework.context.ApplicationContext;
  import org.springframework.context.ApplicationContextAware;
  import org.springframework.stereotype.Component;
  
  /**
   * 
   */
  @Component("serviceFacadeProcessor")
  public class ServiceFacadeProcessor implements BeanPostProcessor, ApplicationContextAware
  {
  
      private static ApplicationContext applicationContext = null;
  
      @Override
      public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException
      {
          return bean;
      }
  
      @Override
      public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException
      {
          Class&lt;?&gt; clz = bean.getClass();
          Class&lt;?&gt;[] tmpInterfaces = clz.getInterfaces();
          System.out.println("ServiceFacadeProcessor : " + bean);
          if (tmpInterfaces != null &amp;&amp; tmpInterfaces.length == 1
                  &amp;&amp; tmpInterfaces[0].isAnnotationPresent(ServiceFacade.class))
          {
  
              System.out.println("Find serviceFacade &gt;&gt;&gt;&gt;");
              Class&lt;?&gt;[] interfaces = Arrays.copyOf(tmpInterfaces, tmpInterfaces.length + 1);
  
              interfaces[tmpInterfaces.length] = Service.class;
              ClassLoader cl = bean.getClass().getClassLoader();
              ServiceLayer serviceLayerBean = applicationContext.getBean("serviceLayer", ServiceLayer.class);
              Object t = Proxy.newProxyInstance(cl, interfaces, serviceLayerBean);
              System.out.println("Find serviceFacade &lt;&lt;&lt;&lt;");
              return t;
          }
  
          return bean;
  
      }
  
      @Override
      public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
      {
          ServiceFacadeProcessor.applicationContext = applicationContext;
      }
  
  }
  </code></pre>
  
  <p>So, my problem is not the configuration, my problem is how to attach Service interface to spring container in order to be caught by BeanPostProcessor and create dynamic proxy for it. It's is my solution so far maybe I'm missing something, but if someone have better way doing it, just let me now.
  Thanks in advance</p>
  
  <p>Solution:</p>
  
  <pre><code>/**
   * 
   */
  package org.finki.auction.services.annotation;
  
  import java.lang.reflect.Proxy;
  import java.util.Arrays;
  
  import org.finki.auction.services.Service;
  import org.finki.auction.services.ServiceLayer;
  import org.springframework.beans.BeansException;
  import org.springframework.beans.factory.FactoryBean;
  import org.springframework.context.ApplicationContext;
  import org.springframework.context.ApplicationContextAware;
  import org.springframework.stereotype.Component;
  
  /**
   * @author
   * 
   */
  @Component
  public class ServiceFactoryBean implements FactoryBean&lt;Service&gt;, ApplicationContextAware
  {
  
      private static ApplicationContext applicationContext = null;
  
      @Override
      public Service getObject() throws Exception
      {
  
          Class&lt;?&gt;[] tmpInterfaces = Service.class.getInterfaces();
          Class&lt;?&gt;[] interfaces = Arrays.copyOf(tmpInterfaces, tmpInterfaces.length + 1);
          interfaces[tmpInterfaces.length] = Service.class;
          ServiceLayer serviceLayerBean = applicationContext.getBean("serviceLayer", ServiceLayer.class);
          ClassLoader cl = serviceLayerBean.getClass().getClassLoader();
          Object t = Proxy.newProxyInstance(cl, interfaces, serviceLayerBean);
          return (Service) t;
      }
  
      @Override
      public Class&lt;?&gt; getObjectType()
      {
          return Service.class;
      }
  
      @Override
      public boolean isSingleton()
      {
          return true;
      }
  
      @Override
      public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
      {
          ServiceFactoryBean.applicationContext = applicationContext;
      }
  
  }
  </code></pre>
  
  <p>Also need to delete BeanPostProcessor and annotation.</p>