Spring Annotations: Proxy

12
Spring’s annotations: Proxy José Canfrán (Osoco) September 2015 Programming Gotchas & Pitfalls Series

Transcript of Spring Annotations: Proxy

Page 1: Spring Annotations: Proxy

Spring’s annotations: Proxy

José Canfrán (Osoco)September 2015

Programming Gotchas & Pitfalls Series

Page 2: Spring Annotations: Proxy

@Transactional1

Page 3: Spring Annotations: Proxy

Ejemplo

package es.osoco.lightTalk

import org.springframework.transaction.annotation.Transactional

class TransactionalService {

@Transactional def firstMethod() { anotherMethod() // code }

@Transactional // @Transactional(propagation = Propagation.REQUIRES_NEW) private anotherMethod() { // code }}

Page 4: Spring Annotations: Proxy

Spring: Proxy

La anotación Transactional de Spring crea un proxy en tiempo de ejecución de la clase, el cual tiene a su vez una instancia de la clase original.Todas las llamadas a métodos transaccionales son interceptadas por el proxy, que es el encargado de iniciar una transacción, unirse a la existente… y llamar al método del servicio.Pero si se hace una llamada a métodos del mismo servicio, el proxy no podrá interceptarla al encontrarnos por debajo de él, en su instancia del servicio y no se ejecutará la condiciones de transacción que hayamos puesto.

Page 5: Spring Annotations: Proxy

Posibles soluciones

● Grails < 2.3.1○ Usar .withTransaction()

● Grails > 2.3.1○ Usar @grails.transaction.Transactional: Durante la compilación

mediante una transformación AST, se crea un nuevo método por cada método anotado dentro de una GrailsTransactionTemplate que ejecuta el código del original con los ajustes de transacción.Ya no existe proxy y como se ha hecho la misma operación con todos los métodos no hay problemas con las llamadas directas. (Puede fallar con la anotación @CompileStatic)

Page 6: Spring Annotations: Proxy

@Cacheable2

Page 7: Spring Annotations: Proxy

Ejemplo

package es.osoco.lightTalk

import org.springframework.cache.annotation.Cacheable

class CacheableService {

def firstMethod() { anotherMethod(param1, param2) // code }

@Cacheable private anotherMethod(param1, param2) { // code }}

Page 8: Spring Annotations: Proxy

Solución3

Page 9: Spring Annotations: Proxy

Obtener proxy: En el servicio

package es.osoco.lightTalk

import org.springframework.cache.annotation.Cacheable

class CacheableService {

def firstMethod() { proxy.anotherMethod(param1, param2) // code }

@Cacheable private anotherMethod(param1, param2) { // code }

private getProxy() { def proxy = grailsApplication.mainContext.cacheableService } }

De este modo obtenemos el proxy para llamar al método a través de él.

Page 10: Spring Annotations: Proxy

Obtener proxy: Genérico

class BootStrap {

def grailsApplication def init = { servletContext -> for( sc in grailsApplication.serviceClasses) { sc.clazz.metaClass.getMyProxy = { ->

grailsApplication.mainContext.getBean(sc.propertyName) } } }

De este modo estará disponible la variable myProxy con el proxy correspondiente en cada servicio.

Page 11: Spring Annotations: Proxy

Bibliografía

◉ Programming Grails (0’Reilly) Burt Beckwith, ISBN: 9 781449 323936

◉ Documentación Grails https://grails.org/documentation.html

Page 12: Spring Annotations: Proxy

Any questions ?You can find me at

◉ @jose_cg

Thanks!

This work is licensed under a Creative Commons Attribution 4.0 International License.