Red de conocimiento informático - Problemas con los teléfonos móviles - ¿Cuándo pone Spring la conexión sql en el subproceso local?

¿Cuándo pone Spring la conexión sql en el subproceso local?

Las instancias de Bean administradas en Spring son singletons [tipo sigleton] de forma predeterminada, y también hay tipos de prototipos

Según su alcance, se pueden dividir en sigleton, prototipo, solicitud, sesión y sesión global.

Los singleton en Spring son ligeramente diferentes de los singleton en los patrones de diseño, donde solo hay una instancia para toda la aplicación. Los singleton en Spring son ligeramente diferentes de los singleton en los patrones de diseño, donde solo hay una instancia para toda la aplicación, mientras que los singleton en Spring son solo una instancia en el contenedor de IoC.

Sin embargo, la instancia única en Spring no afectará el acceso concurrente de la aplicación, no habrá problemas de espera entre subprocesos y no habrá problemas de interbloqueo, porque la mayor parte del tiempo el cliente accede us Objetos comerciales en la aplicación, y estos objetos comerciales no tienen restricciones de concurrencia de subprocesos, pero en este momento no debemos establecer aquellas variables miembro en los objetos comerciales que pueden provocar errores fácilmente.

Las variables miembro en los objetos comerciales serán objetos disfrutados en subprocesos concurrentes durante el acceso concurrente, y luego

En este momento

Situaciones inesperadas surgir.

Por lo tanto, todos los objetos comerciales con variables miembro (como xxxDao en Dao o xxxService en el controlador) en nuestro servidor Eic serán accedidos por múltiples subprocesos, por lo que estos objetos no ocurrirán problemas de sincronización (como como causando

excepciones de inserción y actualización en la base de datos)?

Y nuestros beans de entidad se pasan del cliente al backend del controlador--gt; service--gt Dao; ¿Tiene problemas para manejar los beans de entidad que pasamos al backend?

Respuesta: [Los beans de entidad no son singleton] y Spring no los administra cada vez que actualizamos manualmente aquellos como EMakeType et = new EMakeType();;, por lo que incluso aquellos que procesan lo que enviamos. La clase de procesamiento de datos empresarial es manejada por varios subprocesos, pero los datos que procesan no están desbloqueados. Cada subproceso tiene su propia copia de los datos, por lo que no hay problemas de sincronización entre subprocesos y datos. Pero esos objetos en Dao

xxxDao o xxxService en el controlador son singleton, por lo que habrá problemas de sincronización de subprocesos. Pero dicho esto, aunque varios procesos accederán a estos objetos al mismo tiempo, accedemos a ellos mediante el método

. Estas clases generalmente no contienen variables miembro. El ibatisDao en Dao está empaquetado por el marco. ha pasado Probado, no habrá problemas de sincronización de subprocesos. Entonces, el problema radica en los objetos comerciales de nuestro propio sistema, por lo que debemos prestar atención al hecho de que no debe haber variables miembro independientes en estos objetos comerciales, de lo contrario se producirá un error.

Entonces, nuestros objetos comerciales en la aplicación tienen los siguientes ejemplos:

Variables miembro del controlador Lista y paperService:

clase pública TestPaperController extends BaseController {

lista int final estática privada = 0;

@Autowired

@Qualifier("papersService")

servicio de documentos TestPaperService privado;

página pública queryPaper (int pageSize, int page, TestPaper paper) arroja EicException{

RowSelection localRowSelection = getRowSelection( pageSize, page,

Listlt paperList = papersService.queryPaper(paper, localRowSelection);

Página localPage = nueva página (página, localRowSelection.getTotalRows(),

paperList

return localPage

}

Variable miembro ibatisEntityDao dentro del servicio:

@SuppressWarnings("unchecked")

@Service("papersService")

@Transactional (rollbackFor = { Exception.class })

clase pública TestPaperServiceImpl implementa TestPaperService {

@Autowired

@Qualifier("ibatisEntityDao")

privado IbatisEntityDao ibatisEntityDao;

cadena final estática privada NAMESPACE_TESTPAPER = "com.

cadena final estática privada BO_NAME[] = { "Repositorio de trabajos de prueba" };

cadena final estática privada BO_NAME2[] = { "Preguntas de configuración del examen" };

cadena final estática privada BO_NAME1[] = { "Tipo de pregunta de examen del examen" }; >Cadena final estática privada NAMESPACE_TESTQUESTION="com.its.exam.testpaper.model.TestQuestion";

public TestPapergt; queryPaper(TestPaper paper, RowSelection paramRowSelection) lanza EicException{

try {

return (Listlt. TestPapergt;) ibatisEntityDao.queryForListWithPage(

NAMESPACE_TESTPAPER, "queryPaper", paper, paramRowSelection);

} catch (Excepción) {

excepción.printStackTrace(); p> throw new EicException(exception, "eic", "0001", BO_NAME);

}

}

Como puede ver en lo anterior, Aunque nuestra aplicación contiene variables miembro, no hay ningún problema de sincronización de subprocesos porque la variable miembro privada TestPaperService papersService del controlador;

es una variable miembro y nuestro objetivo es inyectarla y crear una instancia de ella. variable miembro. lista int final estática privada = 0; es una variable final y no cambiará.

El IbatisEntityDao ibatisEntityDao; en servicio privado es un problema de sincronización de subprocesos del marco en sí, y la solución probablemente sea usar ThreadLocal; consulte los detalles a continuación.

El siguiente es un objeto de negocio testPaper.getClass() obtenido a través de BeanFactory getBean. Después de obtenerlo y acceder a él a través de diferentes navegadores de clientes, se pueden sacar las siguientes conclusiones:

Gestión de contenedores SpringIoC. El bean es una instancia única porque los diferentes exam.testpaper.service.impl.TestPaperServiceImplastic.Beans son instancias únicas.

TestPaperServiceImpl$$EnhancerByCGLIB$$584b889d

---------------------El sigleton en primavera, esta es la aplicación completa real, aquí hay una ejemplo: clase

com.its.exam.testpaper.service.impl.TestPaperServiceImpl$$EnhancerByCGLIB$$584b889d

-------- ------ ----------spring in the sigleton , que en realidad es la aplicación completa a continuación en un ejemplo: clase

com.its.exam.testpaper.service .impl.584b889d

------------------------El sigleton en primavera, esta es en realidad la aplicación completa. Un ejemplo: clase

<. p>com.its.exam.testpaper.service.impl.TestPaperServiceImpl$$EnhancerByCGLIB$$584b889d

El marco Spring admite singletons mediante el uso del registro singleton. Para lograr esto, consulte este artículo en "Spring Design Patrones - Patrón Singleton".

En cuanto a

Cómo implementa Spring la seguridad de subprocesos de beans con estado [como RequestContextHolder,

TransactionSynchronizationManager, LocaleContextHolder], el principio es el siguiente

Para obtener más detalles, consulte

"Enciclopedia ThreadLocal Baidu" y también consulte este artículo para lectura en línea: "Introducción a Spring Declarative Transaction Management ThreadLocal y JDKProxy".

Aunque la implementación ThreadLocal en el Listado de Código 9-3 parece ingenua, es similar en ideas de implementación a la clase ThreadLocal proporcionada por el JDK.

En

la programación multiproceso Java, para garantizar el acceso seguro a las variables que disfrutan varios subprocesos, generalmente se usa sincronizado para garantizar que solo acceda un subproceso. variables que disfrutaba muchísimo al mismo tiempo. Sin embargo, en algunos casos, sincronizado no puede garantizar que varios subprocesos lean y escriban correctamente las variables que disfrutamos. Por ejemplo, si hay una variable de clase en una clase, la variable de clase puede ser leída o escrita por múltiples métodos de clase. Cuando varios subprocesos operan en instancias de la clase, si un subproceso lee buscar o escribir. la variable de clase, entonces la variable de clase se leerá o escribirá incorrectamente, incluso si se agrega sincronizado antes del método de clase, aún no será válido porque el mismo hilo durante el período de tiempo entre las dos llamadas al método Se liberará el bloqueo p>

, entonces otros subprocesos pueden acceder al objeto y el objeto será liberado. En este caso puedes poner la variable de clase en un objeto de tipo ThreadLocal para que la variable tenga una copia separada en cada hilo para que no haya un hilo leyendo y otro hilo modifique la situación.

Para ilustrar el impacto del acceso multiproceso en las variables de clase y

variables ThreadLocal, QuerySvc establece las variables de clase sql y ThreadLocal respectivamente, y las usa para crear

Un objeto de instancia de QuerySvc y luego genera múltiples subprocesos. Estos subprocesos configuran diferentes objetos de instancia de SQL y luego llaman al método de ejecución para leer el valor de SQL y determinar si es el valor escrito en el método establecido

. Esta situación es similar a una aplicación web, en la que varios subprocesos de solicitud llevan diferentes condiciones de consulta para acceder a una instancia de servlet, y luego el servlet llama al objeto comercial y pasa diferentes entradas de consulta

, y finalmente garantiza que cada solicitud Los resultados son todos los resultados de las condiciones de consulta correspondientes.

Primero cree un objeto de instancia de QuerySvc y luego cree varios subprocesos para llamar a los métodos de configuración y ejecución de QuerySvc. Cada subproceso pasa por sql diferente. Como se puede ver en los resultados de ejecución, sql. No se garantiza que el valor de una variable sea el mismo en ejecutar y establecer

set; y el valor en ThreadLocal es siempre el mismo que el valor establecido

Por lo tanto, la seguridad de los subprocesos puede obtenerse utilizando ThreadLocal.

Si varios subprocesos accederán a un objeto y las variables de clase del objeto se leen y escriben mediante diferentes métodos de clase, puede utilizar ThreadLocal en lugar de la variable de clase para lograr la seguridad de los subprocesos.

Comparación de mecanismos de sincronización. ¿Cuáles son las ventajas de los mecanismos ThreadLocal y ThreadSynchronization? Tanto el mecanismo ThreadLocal como el ThreadSynchronization están diseñados para resolver el problema del acceso conflictivo a las mismas variables por parte de múltiples subprocesos.

En el mecanismo de sincronización, el mecanismo de bloqueo del objeto garantiza que solo un hilo pueda acceder a la variable a la vez. En este momento, las variables son disfrutadas por múltiples subprocesos. El uso del mecanismo de sincronización requiere que el programa analice cuidadosamente cuestiones complejas como cuándo leer y escribir variables, cuándo bloquear objetos y cuándo liberar bloqueos de objetos. Los programas son relativamente más difíciles.

ThreadLocal resuelve el problema del acceso simultáneo de múltiples subprocesos desde otro ángulo. Proporciona una copia separada de variables para cada subproceso, aislando así las diferencias entre múltiples subprocesos. >

Violación de acceso a datos. Dado que cada hilo tiene su propia copia de la variable, no es necesario sincronizar la variable. ThreadLocal proporciona un objeto ****hedge seguro para subprocesos, que permite encapsular variables inseguras en ThreadLocal al escribir código de subprocesos múltiples.

Dado que ThreadLocal puede acomodar cualquier tipo de objeto,

get() proporcionado por versiones inferiores del JDK devolverá un objeto Object, y el objeto Object requiere conversión de tipo de conversión. Sin embargo, JDK

5.0 resuelve este problema mediante el uso de genéricos, simplificando así el uso de ThreadLocal hasta cierto punto. Code List 9 2 utiliza la nueva versión JDK

5.0 de ThreadLocal.

En resumen, el mecanismo de sincronización utiliza el método "tiempo por espacio" para compartir recursos multiproceso, mientras que ThreadLocal utiliza el método "espacio por tiempo". El primero solo proporciona una copia de la variable para que diferentes subprocesos pongan en cola para acceder, mientras que el segundo proporciona a cada subproceso una copia de la variable para que se pueda acceder a ella simultáneamente sin afectarse entre sí.

Spring usa ThreadLocal para resolver problemas de seguridad de subprocesos

Sabemos que, en general, solo los beans sin estado pueden operar en un entorno de subprocesos múltiples*** * , y la mayoría de los beans en Spring se pueden declarar como alcance singleton.

Esto se debe a que Spring usa

ThreadLocal para estados no seguros para subprocesos de ciertos beans (como RequestContextHolder,

TransactionSynchronizationManager, LocaleContextHolder, etc.).

ThreadLocal también los hace seguros para subprocesos, porque los beans con estado pueden estar en varios subprocesos.

Las aplicaciones Web generales se dividen en tres capas: capa de presentación, capa de servicio y capa de persistencia. La lógica correspondiente está escrita en diferentes capas y la capa inferior abre llamadas de función a la capa superior a través de interfaces. En términos generales, todas las llamadas al programa, desde la recepción de una solicitud hasta la devolución de una respuesta, pertenecen al mismo hilo, como se muestra en la Figura 9.2:

Por lo tanto, puede almacenar algunas variables que no son seguras para subprocesos en En ThreadLocal, en el Al llamar al hilo de la misma solicitud y respuesta, todos los objetos asociados están referenciados a la misma variable.

Dado que conn en ① es una variable miembro y el método addTopic() no es seguro para subprocesos, se debe crear una nueva instancia de TopicDao (no enfundada) cuando se utiliza. A continuación se explica cómo convertir el "estado" de conn que no es seguro para subprocesos utilizando ThreadLocal:

Listado de código 4 TopicDao:

import java.sql.Statement

;

public class TopicDao {

① Utilice ThreadLocal para guardar la variable de conexión

private static ThreadLocal connThreadLocal = new ThreadLocal()

public static Connection getConnection; (){

② Si ​​connThreadLocal no crea una conexión correspondiente para el subproceso, cree una nueva conexión

y guárdela en la variable local del subproceso.

if (connThreadLocal.get() == null) {

Conexión conn = ConnectionManager.getConnection();

connThreadLocal.set(conn); /p>

return conn;

}else{

return connThreadLocal.get(); ③ Devuelve directamente variables locales del hilo

}

}

}

public void addTopic() {

④ Obtenga la variable local del hilo de ThreadLocal para obtener la conexión correspondiente al hilo < / p>

Estadística de declaración = getConnection().createStatement();

}

}

}

}< / p>

Diferentes subprocesos usan TopicDao Cuando diferentes subprocesos usan TopicDao, primero determine si connThreadLocal está vacío, significa que el subproceso actual no tiene el

Objeto de conexión, se creará un objeto de conexión y se agregará a la variable del hilo local; si no está vacío, significa que el hilo actual ya tiene un objeto de conexión

y se puede usar directamente. . Esto garantiza que diferentes subprocesos utilicen la conexión asociada al subproceso y no las conexiones de otros subprocesos, por lo que el TopicDao se puede compartir individualmente.