2012-09-19 22 views
5

ci sono alcune informazioni nel motore Tomcat che vogliamo accedere fase di esecuzione, quindi abbiamo le seguenti nel nostro contesto app (ottenuto questo da this blog post):Come si fa a iniettare un proxy in un servizio?

<bean id="tomcatEngineProxy" class="org.springframework.jmx.access.MBeanProxyFactoryBean"> 
    <property name="objectName" value="Catalina:type=Engine" /> 
    <property name="proxyInterface" value="org.apache.catalina.Engine" /> 
    <property name="useStrictCasing" value="false" /> 
</bean> 

In un controller, abbiamo poi autowired in in questo modo:

@Autowired 
private MBeanProxyFactoryBean tomcatEngineProxy = null; 

non possiamo filo nella org.apache.catalina.Engine come nel post del blog, perché quella classe non è disponibile per noi al momento della compilazione. È disponibile solo in fase di esecuzione con tutte le diverse versioni di tomcat in esecuzione su macchine diverse.

Siamo stati in grado di ottenere le informazioni necessarie da questo @Autowire utilizzando la riflessione. Ora, vogliamo spostare questa funzionalità in un servizio. Ho aggiunto che questo nostro contesto app:

<bean id="myService" class="com.foo.bar.MyServiceImpl"> 
    <constructor-arg ref="tomcatEngineProxy" /> 
</bean> 

E la classe si presenta così:

public class MyServiceImpl implements MyService 
{ 
    public MyServiceImpl(MBeanProxyFactoryBean tomcatEngineProxy) throws Exception 
    { 
     //stuff with the proxy 
    } 
    ..... 
} 

Quando faccio questo, ottengo il seguente errore:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'myService' defined in ServletContext resource [/WEB-INF/spring/root-context.xml]: Unsatisfied dependency expressed through constructor argument with index 0 of type [org.springframework.jmx.access.MBeanProxyFactoryBean]: Could not convert constructor argument value of type [$Proxy44] to required type [org.springframework.jmx.access.MBeanProxyFactoryBean]: Failed to convert value of type '$Proxy44 implementing org.apache.catalina.Engine,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised' to required type 'org.springframework.jmx.access.MBeanProxyFactoryBean'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [$Proxy44 implementing org.apache.catalina.Engine,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [org.springframework.jmx.access.MBeanProxyFactoryBean]: no matching editors or conversion strategy found 

sapendo praticamente nulla su come funzionano i proxy e su come usarli, non sono sicuro su come fare questo lavoro. C'è qualche dichiarazione che posso usare per il mio arg costruttore che combacerà? Cosa c'è di diverso tra @Autowire nel controller che funziona e il costruttore arg che non funziona?

risposta

4

È perché il bean fabbrica sta esponendo il risultato come l'interfaccia del motore:

<property name="proxyInterface" value="org.apache.catalina.Engine" /> 

Quindi, se si tenta di filo nella "tomcatEngineProxy" fagiolo per sé, è solo l'assegnazione compatibile è quello di "org.apache. catalina.Engine ", poiché il proxy creato implementa solo quell'interfaccia.

provare riferimento il fagiolo fabbrica direttamente invece (si noti la e commerciale, che è la sintassi per trovare il fagiolo reale della fabbrica che ha creato l'oggetto invece che l'oggetto stesso):

<constructor-arg ref="&tomcatEngineProxy" /> 

How to inject FactoryBean instead of object it produces?

+0

Perfetto! Ha funzionato come un fascino. Non ho visto prima quella sintassi. Dovevo farlo in questo modo: '', ma è solo questione di rendere l'XML felice. Grazie! – dnc253

+0

np. non provarlo in un'espressione EL perché è rotto :) Ho un bug in spring per quello. – Matt

0

credo che @Autowired opere in quanto il legame è fatto in base al tipo di Bean (cioè MBeanProxyFactoryBean), tuttavia il legame con l'argomento del costruttore è fatto per nome e il nome che hai fornito tomcatEngineProxy non corrisponde al tipo che ci si aspetta poiché il tipo di bean creato con FactoryBean è diverso da quello di FactoryBean.

Sembra la soluzione più semplice sarà quello di cambiare MyServiceImpl di essere:

public class MyServiceImpl implements MyService 
{ 
    @Autowired 
    private MBeanProxyFactoryBean tomcatEngineProxy; 

    public MyServiceImpl() throws Exception 
    { 
     //stuff with the proxy 
    } 
    ..... 
} 

Questo dovrebbe fare il trucco.

+0

Come ho detto sopra, non abbiamo org.apache.catalina.Engine disponibile al momento della compilazione. Rendendolo disponibile ci legheremo qualunque versione di tomcat con cui è stata costruita, e abbiamo versioni diverse di tomcat in esecuzione su tutti i diversi server. Non so come, ma l'autowiring nel controller ha funzionato decisamente. – dnc253

+0

@ dnc253: Scusa - Ho perso quella parte della domanda. – RonK

Problemi correlati