java spring casting aop proxy-classes

java - ¿Arreglando BeanNotOfRequiredTypeException en Spring Proxy cast en un bean no singleton?



casting aop (8)

Esto es solo una conjetura, pero intente crear una interfaz InnerThreadInterface, luego deje que la clase InnerThread la extienda.

Después de eso deberías poder hacer:

InnerThreadInterface inner = ctx.getBean ("innerThread", InnerThread.class);

Tengo un problema con la extracción de un bean Spring desde un contexto de aplicación.

Cuando lo intento

InnerThread instance = (InnerThread) SpringContextFactory.getApplicationContext().getBean("innerThread", InnerThread.class);

Yo obtengo;

org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named ''innerThread'' must be of type [com.generic.InnerThread], but was actually of type [$Proxy26]

Sin la clase especificada en la llamada a getBean (), obtengo una ClassCastException (que puede ver en detalle a continuación).

El bean InnerThread se está inicializando como un no singleton, porque necesito varias instancias. La clase InnerThread también extiende Thread. Lo interesante es que este error aparece en OuterThread, que se configura exactamente de la misma manera que lo es InnerThread.

He intentado incluir todos los listados de códigos relevantes / seguimientos de pila a continuación. ¿Podría alguien con más experiencia en la primavera decirme qué está pasando aquí?

Listado de Código / Configuración

Fragmento de OuterThread.java:

public class OuterThread extends Thread { private Queue<InnerThread> createInnerThreads() { Queue<InnerThread> threads = new ArrayBlockingQueue(); ApplicationContext ctx = SpringContextFactory.getApplicationContext(); int i = 0; for (SearchRule search : searches) { logger.debug("Number of times looped " + i++); //Seprated lines to get a better sense of what is going on Object proxy = ctx.getBean("innerThread", InnerThread.class); logger.debug(ReflectionToStringBuilder.toString(proxy)); logger.debug("proxy.getClass(): " + proxy.getClass()); logger.debug("proxy.getClass().getClassLoader(): " + proxy.getClass().getClassLoader()); logger.debug("proxy.getClass().getDeclaringClass(): " + proxy.getClass().getDeclaringClass()); logger.debug("InnerThread.class.getClassLoader(): " + InnerThread.class.getClassLoader()); //---Exception here--- InnerThread cst = (InnerThread) proxy; threads.add(cst); } return threads; } public static void main(String[] args) throws Exception { try { OuterThread instance = (OuterThread) SpringContextFactory.getApplicationContext().getBean("outerThread", OuterThread.class); instance.run(); } catch (Exception ex) { logger.error("Fatal exception.", ex); throw ex; } } }

SpringContextFactory.java:

public class SpringContextFactory { static final Logger logger = LoggerFactory.getLogger(SpringContextFactory.class); private static ApplicationContext ctx; private static final String DEFAULT_PATH = "META-INF/app-context.xml"; public static ApplicationContext getApplicationContext() { return getApplicationContext(DEFAULT_PATH); } public static synchronized ApplicationContext getApplicationContext(String path) { if (ctx == null) return createApplicationContext(path); else return ctx; } private static ApplicationContext createApplicationContext(String path) { if (logger.isDebugEnabled()) logger.debug("Loading Spring Context..."); ctx = new ClassPathXmlApplicationContext(path); if (logger.isDebugEnabled()) logger.debug("Spring Context Loaded"); return ctx; } }

app-context.xml:

<?xml version="1.0" encoding="UTF-8"?> <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-2.5.xsd"> <!-- persistence context from separate jar --> <import resource="persistence-context.xml"/> <bean id="outerThread" class="com.generic.OuterThread" scope="prototype"/> <bean id="innerThread" class="com.generic.InnerThread" scope="prototype"/> </beans>

Traza de pila

2009-05-08 14:34:37,341 [main] DEBUG com.generic.OuterThread.init(OuterThread.java:59) - Initializing OuterThread object, com.generic.OuterThread@1c8fb4b[em=org.hibernate.ejb.EntityManagerImpl@e2892b,currentTime=java.util.GregorianCalendar[time=1241634874841,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/New_York",offset=-18000000,dstSavings=3600000,useDaylight=true,transitions=235,lastRule=java.util.SimpleTimeZone[id=America/New_York,offset=-18000000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2009,MONTH=4,WEEK_OF_YEAR=19,WEEK_OF_MONTH=2,DAY_OF_MONTH=6,DAY_OF_YEAR=126,DAY_OF_WEEK=4,DAY_OF_WEEK_IN_MONTH=1,AM_PM=1,HOUR=2,HOUR_OF_DAY=14,MINUTE=34,SECOND=34,MILLISECOND=841,ZONE_OFFSET=-18000000,DST_OFFSET=3600000],maxConcurrentThreads=5,reconId=3,reportUsername=TEST,useOffset=false,username=removed,uuid=bf61494d-ff96-431c-a41f-1e292d0c9fbe,name={T,h,r,e,a,d,-,1},priority=5,threadQ=<null>,eetop=0,single_step=false,daemon=false,stillborn=false,target=<null>,group=java.lang.ThreadGroup[name=main,maxpri=10],contextClassLoader=sun.misc.Launcher$AppClassLoader@11b86e7,inheritedAccessControlContext=java.security.AccessControlContext@1524d43,threadLocals=<null>,inheritableThreadLocals=java.lang.ThreadLocal$ThreadLocalMap@2cbc86,stackSize=0,nativeParkEventPointer=0,tid=9,threadStatus=0,parkBlocker=<null>,blocker=<null>,blockerLock=java.lang.Object@a68fd8,stopBeforeStart=false,throwableFromStop=<null>,uncaughtExceptionHandler=<null>] 2009-05-08 14:34:37,341 [main] DEBUG org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.doJoinTransaction(ExtendedEntityManagerCreator.java:385) - No local transaction to join 2009-05-08 14:34:37,529 [main] DEBUG com.generic.OuterThread.createInnerThreads(OuterThread.java:139) - Number of times looped 0 2009-05-08 14:34:37,529 [main] DEBUG org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:458) - Creating instance of bean ''searchThread'' with merged definition [Root bean: class [com.generic.InnerThread]; scope=prototype; abstract=false; lazyInit=false; autowireCandidate=true; autowireMode=0; dependencyCheck=0; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [META-INF/app-context.xml]] 2009-05-08 14:34:37,545 [main] DEBUG com.generic.InnerThread.<init>(InnerThread.java:50) - Constructing InnerThread object, com.generic.InnerThread@1080876[em=<null>,coolScheme=<null>,coolUrl=<null>,date=<null>,error=<null>,millisecondsTaken=0,thresholdMet=false,reconId=0,result=-2,searchId=0,username=<null>,uuid=<null>,name={T,h,r,e,a,d,-,2},priority=5,threadQ=<null>,eetop=0,single_step=false,daemon=false,stillborn=false,target=<null>,group=java.lang.ThreadGroup[name=main,maxpri=10],contextClassLoader=sun.misc.Launcher$AppClassLoader@11b86e7,inheritedAccessControlContext=java.security.AccessControlContext@1524d43,threadLocals=<null>,inheritableThreadLocals=java.lang.ThreadLocal$ThreadLocalMap@3aef16,stackSize=0,nativeParkEventPointer=0,tid=10,threadStatus=0,parkBlocker=<null>,blocker=<null>,blockerLock=java.lang.Object@126c6ea,stopBeforeStart=false,throwableFromStop=<null>,uncaughtExceptionHandler=<null>] 2009-05-08 14:34:37,545 [main] DEBUG org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:203) - Returning cached instance of singleton bean ''entityManagerFactory'' 2009-05-08 14:34:37,545 [main] DEBUG org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:203) - Returning cached instance of singleton bean ''org.springframework.transaction.config.internalTransactionAdvisor'' 2009-05-08 14:34:37,560 [main] DEBUG org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource.getTransactionAttribute(AbstractFallbackTransactionAttributeSource.java:108) - Adding transactional method [report] with attribute [PROPAGATION_REQUIRED,ISOLATION_DEFAULT] 2009-05-08 14:34:37,560 [main] DEBUG org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.buildAdvisors(AbstractAutoProxyCreator.java:494) - Creating implicit proxy for bean ''searchThread'' with 0 common interceptors and 1 specific interceptors 2009-05-08 14:34:37,560 [main] DEBUG org.springframework.aop.framework.JdkDynamicAopProxy.getProxy(JdkDynamicAopProxy.java:113) - Creating JDK dynamic proxy: target source is SingletonTargetSource for target object [com.generic.InnerThread@1080876] 2009-05-08 14:34:37,591 [main] DEBUG com.generic.OuterThread.createInnerThreads(OuterThread.java:141) - $Proxy26@1594a88[h=org.springframework.aop.framework.JdkDynamicAopProxy@1f0cf51] 2009-05-08 14:34:37,591 [main] DEBUG com.generic.OuterThread.createInnerThreads(OuterThread.java:142) - proxy.getClass(): class $Proxy26 2009-05-08 14:34:37,591 [main] DEBUG com.generic.OuterThread.createInnerThreads(OuterThread.java:143) - proxy.getClass().getClassLoader(): sun.misc.Launcher$AppClassLoader@11b86e7 2009-05-08 14:34:37,591 [main] DEBUG com.generic.OuterThread.createInnerThreads(OuterThread.java:144) - proxy.getClass().getDeclaringClass(): null 2009-05-08 14:34:37,591 [main] DEBUG com.generic.OuterThread.createInnerThreads(OuterThread.java:145) - InnerThread.class.getClassLoader(): sun.misc.Launcher$AppClassLoader@11b86e7 2009-05-08 14:34:37,591 [main] ERROR com.generic.OuterThread.run(OuterThread.java:101) - Exception in OuterThread, ending reconciliation. java.lang.ClassCastException: $Proxy26 cannot be cast to com.generic.InnerThread at com.generic.OuterThread.createInnerThreads(OuterThread.java:148) at com.generic.OuterThread.run(OuterThread.java:65) at com.generic.OuterThread.main(OuterThread.java:170)

Preguntas similares que no responden a mi pregunta.


Otra forma de manejar este problema sería implementar una interfaz y solicitar la interfaz desde Spring, el proxy implementaría completamente la interfaz y la conversión no debería tener un problema.


Tuve este problema a pesar de que hice referencia a CGLIB y usé la configuración proxy-target-class = "true". Determiné ehcache: la etiqueta de anotación era la culpable ... Eliminar la siguiente configuración solucionó esto para mí. Afortunadamente, pude utilizar el almacenamiento en caché de nivel 2 de hibernación en lugar de tener que usar el almacenamiento en caché declarativo de ehcache.

<ehcache:annotations> <ehcache:caching id="myCacheModel" cacheName="myCache"/> <ehcache:flushing id="myFlushModel" cacheNames="myCache" when="after"/> </ehcache:annotations>


Una forma de resolver este problema es extendiendo la interfaz ejecutable y creando la suya propia:

public class MyInterface extends Runnable { // your own method declarations here void doSomething(); ... }

Entonces deberías implementar tu interfaz en lugar de la ejecutable:

@Component("myInterface") @Scope("prototype") public class MyInterfaceImpl extends MyInterface { // your own method declarations here public void doSomething(){ ... } // implement run from Runnable Interface @Transactional public void run(){ ..... } ... }

Esto funcionará bien:

... MyInterface mynterface = SpringApplicationContext.getBean("myInterface", MyInterface.class); myInterface.doSomething(); ExecutorService executor = Executors.newSingleThreadExecutor(); executor.submit(myInterface); ...


Una vez más, después de pasar horas intentando depurar esto, encuentro la respuesta justo después de publicar en .

Un punto clave que dejé fuera de mi pregunta es que InnerThread tiene un método transaccional (perdón, pensé que esto era irrelevante). Esta es la diferencia importante entre OuterThread e InnerThread.

De la documentación de primavera :

Nota

Varias secciones se contraen en un único creador de proxy automático unificado en tiempo de ejecución, que aplica la configuración de proxy más fuerte que cualquiera de las secciones (generalmente de diferentes archivos de definición de bean de XML) especificó. Esto también se aplica a los elementos y.

Para que quede claro: usar ''proxy-target-class = "true"'' en, o los elementos forzarán el uso de los proxies CGLIB para los tres.

Al agregar el problema a mi configuración (basada en persistance-context.xml, que puede ver cargado arriba), parece que se soluciona el problema. Sin embargo, creo que esta puede ser una solución rápida a la solución real.

Creo que tengo algunos problemas más profundos aquí, siendo el número uno que encuentro a Spring tan confuso como tácticamente eliminado. En segundo lugar, probablemente debería usar el TaskExecutor de Spring para iniciar mis hilos. Tercero, mis hilos deberían implementar Runnable en lugar de extender Thread (vea la pregunta SO a continuación).

Ver también


Yo tuve el mismo problema:

Esto es solo una conjetura, pero intente crear una interfaz InnerThreadInterface, luego deje que la clase InnerThread la extienda. Después de eso deberías poder hacer:

Utilizo esta forma en lugar de lo que está publicado arriba y funcionó bien. No había necesidad de establecer la clase proxy-target en true, esto requería más bibliotecas que no estaban en mi classpath.

InnerThreadInterface inner = (InnerThreadInterface)ctx.getBean("innerThread");


cree una interfaz DAO e implemente la interfaz DAO a la clase SERVICE y proporcione los detalles de configuración de la clase SERVICE en el archivo applicationContext.xml, es decir, el archivo de configuración spring y acceda al bean usando la ID de bean y haga referencia a la instancia del proxy así instanciado objetar a la interfaz DAO ... funcionará perfectamente bien ...


@Configuration tu clase @Configuration con

@EnableAspectJAutoProxy(proxyTargetClass = true)

También tienes que añadir la siguiente dependencia:

<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.7.2</version> </dependency>