2013-07-16 8 views
5

In un'applicazione legacy molto grande, ho interfacce e classi che fanno non implementare tali interfacce.Spring: Delega a un wrapper proxy personalizzato per l'iniezione dell'interfaccia

Le interfacce vengono generate in base alla classe in modo che le firme siano uguali (tranne che l'interfaccia aggiunge un'altra eccezione in alto) ei nomi sono simili (quindi è facile trovare il nome della classe dal nome dell'interfaccia).

Per ottenere un'implementazione dell'interfaccia, eseguiamo una serie di chiamate di elaborazione e registrazione, ma fondamentalmente utilizziamo java.lang.reflect.Proxy per delegare alla classe. Semplificata sembra che questo:

// This will create a proxy and invoke handler that calls HelloWorld.doSomething 
HelloWorldInterface i = MyProxyUtil.getInstance(HelloWorldInterface.class); 
i.doSomething(); 

public interface HelloWorldInterface { 
    public void doSomething() throws Exception; 
} 

public class HelloWorld { 
    public void doSomething() { 
    //something 
    } 
} 

E 'possibile con l'elaborazione di primavera annotazione, genericamente @Autowire tutti i campi di tipo *Interface e usufruire primavera MyProxyUtil.getInstance(*Interface.class) per iniettare l'attuazione?

Tale che

@Autowire HelloWorldInterface a; 

HelloWorldInterface b = MyProxyUtil.getInstance(HelloWorldInterface.class); 

@Autowire AnotherInterface c; 

AnotherInterface d = MyProxyUtil.getInstance(AnotherInterface.class); 


a == b 
c == d 

risposta

9

Sì, è necessario implementare un AutowireCandidateResolver.

Ad esempio:

public class ProxyAutowiredCandidateResolver extends SimpleAutowireCandidateResolver { 

    @Override 
    public Object getSuggestedValue(DependencyDescriptor descriptor) { 
     String dependencyClassName = descriptor.getDependencyType().getSimpleName(); 
     if (dependencyClassName.endsWith("Interface")) { 
      return MyProxyUtil.getInstance(descriptor.getDependencyType()); 
     } 

     return super.getSuggestedValue(descriptor); 
    } 

} 

si potrebbe usare un BeanFactoryPostProcessor per configurarlo nel contesto dell'applicazione:

public class AutowireCandidateResolverConfigurer implements BeanFactoryPostProcessor { 

    private AutowireCandidateResolver autowireCandidateResolver; 

    public void postProcessBeanFactory(
      ConfigurableListableBeanFactory beanFactory) throws BeansException { 
     DefaultListableBeanFactory bf = (DefaultListableBeanFactory) beanFactory; 
     bf.setAutowireCandidateResolver(autowireCandidateResolver); 


    } 

    public AutowireCandidateResolver getAutowireCandidateResolver() { 
     return autowireCandidateResolver; 
    } 

    public void setAutowireCandidateResolver(

      AutowireCandidateResolver autowireCandidateResolver) { 
     this.autowireCandidateResolver = autowireCandidateResolver; 
    } 

} 

<bean id="autowireCandidateResolverConfigurer" class="AutowireCandidateResolverConfigurer"> 
     <property name="autowireCandidateResolver"> 
      <bean class="ProxyAutowiredCandidateResolver" /> 
     </property> 
</bean> 
+0

Scusa, ho difficoltà a capire come si configura effettivamente questo per essere utilizzato? Cosa aggiungerei al mio applicationContext.xml? –

+0

@casenelson puoi usare un 'BeanFactoryPostprocessor' per configurare' AutowireCandidateResolver' –

+0

C'è un problema con l'iniezione di Environment con la tua soluzione -> https: // github.com/mariuszs/env-is-null – MariuszS

1

Se sto leggendo correttamente, si dovrebbe essere in grado di definirli in una classe JavaConfig @Configuration annotata e poi usarli altrove.

Dalla documentazione (Spring):

@Configuration 
public class AppConfig { 
    @Bean 
    public MyService myService() { 
     return new MyServiceImpl(); 
    } 
} 

Si potrebbe fare qualcosa di simile:

@Configuration 
public class InterfaceConfig { 
    @Bean 
    public HelloWorldInterface helloWorldInterface() { 
     return MyProxyUtil.getInstance(HelloWorldInterface.class); 
    } 
} 

A quel punto, Primavera avrebbe utilizzato tale definizione ogni volta che era necessario che Bean.

Dovresti collegare in qualche modo la classe @Configuration (scansione del percorso di classe, a livello di programmazione, ecc.), Ma dipende da come stai configurando il contesto dell'applicazione.

Penso che questo dovrebbe funzionare. Ho usato JavaConfig un bel po ', ma mai del tutto simile a questo. Ma sembra ragionevole.

+0

Non è davvero pratico per me per definire ciascuno di questi fagioli nella configurazione (ce ne sono centinaia). Piuttosto, sto cercando un modo per risolvere tutte le interfacce il cui nome termina con Interface attraverso MyProxyUtil. –

+0

Non ho capito quella parte. Se è tutto esistente, non sarebbe difficile scrivere uno script per generare il codice una volta sola. La risposta di Jose sembra interessante, ma non mi era familiare. I proxy sono già gestiti da Spring? Stai cercando di fare qualcosa con loro che richiederebbe loro di essere gestiti da una molla, se no? – Jafoy