2012-09-19 10 views
5

hay alguna información en el motor Tomcat que queremos acceder tiempo de ejecución, por lo que tenemos el siguiente en nuestro contexto aplicación (consiguió esto desde this blog post):¿Cómo se inyecta un proxy en un servicio?

<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> 

En un controlador, que a continuación autowired en de esta manera:

@Autowired 
private MBeanProxyFactoryBean tomcatEngineProxy = null; 

no podemos alambre en org.apache.catalina.Engine al igual que en la entrada del blog, porque esa clase no está disponible para nosotros en tiempo de compilación. Solo está disponible en tiempo de ejecución con todas las diferentes versiones de tomcat que se ejecutan en las diferentes máquinas.

Pudimos obtener la información que necesitábamos de este @Autowire usando la reflexión. Ahora, queremos mover esta funcionalidad a un servicio. He añadido esto a nuestro contexto aplicación:

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

Y la clase tiene este aspecto:

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

Cuando hago esto, me sale el siguiente error:

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 

Conocer básicamente nada acerca de cómo funcionan los proxies y cómo usarlos, no estoy seguro de cómo hacerlo funcionar. ¿Hay alguna declaración que pueda usar para mi constructor arg que coincida? ¿Qué hay de diferente entre @Autowire en el controlador que funciona y el constructor arg que no funciona?

Respuesta

4

Es porque su grano de la fábrica está exponiendo el resultado como la interfaz del motor:

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

Así que si usted trata de alambre en el "tomcatEngineProxy" grano en sí, es sólo la asignación compatible es "org.apache. catalina.Engine ", ya que el proxy creado implementa solo esa interfaz.

tratar referencia al grano de la fábrica directamente en su lugar (nótese el signo que es la línea para encontrar el grano de la fábrica real que crea el objeto en lugar del objeto en sí):

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

How to inject FactoryBean instead of object it produces?

+0

¡Perfecto! Trabajado como un encanto. No he visto esa sintaxis antes. Tenía que hacerlo así: '', pero eso solo es cuestión de hacer feliz al XML. ¡Gracias! – dnc253

+0

np. simplemente no intentes eso en una expresión EL, ya que está rota :) Tengo un error en la primavera para eso. – Matt

0

creo que @Autowired obras desde la unión se realiza de acuerdo con el tipo de la haba (es decir MBeanProxyFactoryBean), sin embargo la unión al argumento del constructor se hace por su nombre y el nombre proporcionado tomcatEngineProxy no coincide con el tipo de esperas ya que el tipo de un bean creado usando FactoryBean es diferente al del FactoryBean.

Parece que la solución más simple habrá que cambiar para ser MyServiceImpl:

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

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

Esto debería hacer el truco.

+0

Como indiqué arriba, no tenemos org.apache.catalina.Engine disponible en tiempo de compilación. Hacer que esté disponible nos vinculará con cualquier versión de tomcat contra la que se haya creado, y tenemos diferentes versiones de tomcat ejecutándose en todos los servidores diferentes. No sé cómo, pero el autovío en el controlador definitivamente funcionó. – dnc253

+0

@ dnc253: Lo siento, me perdí esa parte de la pregunta. – RonK

Cuestiones relacionadas