Spring framework 5 : AOP Around Advice


Como vimos en el post pasado https://devs4j.com/2019/02/28/spring-framework-5-aop-conceptos-basicos/ existen diferentes tipos de advices, en este post nos enfocaremos en Around Advice.

Para poder seguir estos ejemplos es necesario crear un proyecto spring boot simple.

Creación de un servicio de spring

El primer paso para entender como funcionan los advices será crear un servicio de spring, este objeto será nuestro Target object.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

/**
 * @author raidentrance
 *
 */
@Service
public class HelloWorldService {

	private static final Logger log = LoggerFactory.getLogger(HelloWorldService.class);

	public void print() {
		log.info("Hello world");
	}

}

Como vemos nuestro servicio es solo una clase llamada HelloWorldService con un método llamado print().

Around Advice

En este ejemplo interceptaremos las peticiones a la clase HelloWorldService en su método print utilizando un Around Advice, veamos el siguiente ejemplo:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * @author raidentrance
 *
 */
@Aspect
@Component
public class AroundAdviceExample {
	private static final Logger log = LoggerFactory.getLogger(AroundAdviceExample.class);

	@Around("execution(* com.devs4j.service.HelloWorldService.*(..))")
	public Object logAround(ProceedingJoinPoint proceedingJoinPoint) {
		log.info("before advice example");
		Object result = null;
		try {
			result = proceedingJoinPoint.proceed();
		} catch (Throwable e) {
			log.info("There is an exception ", e);
		}
		log.info("after advice example");
		return result;
	}
}

Del código anterior podemos analizar los siguientes puntos:

  • La clase esta anotada con @Component y @Aspect esto permite a spring identificarlo como un bean y como un aspecto.
  • La anotación @Around nos permite utilizar un Around advice.
  • Los advices reciben como parámetro un Pointcut el cual define los objetos que serán afectados por el Advice (Explicaremos Pointcut expression language en otro post).
  • El método recibe como parámetro un objeto que implementa la interfaz JoinPoint, esto nos permite acceder a información del JoinPoint que se interceptó.
  • Lo único que hace nuestro aspecto es imprimir el mensaje before advice example, después ejecuta el método y al final imprime after advice example
  • Los around advices interceptan la petición y deciden si ejecutar o no, esto nos permite hacer algo antes de la ejecución, después ejecutar o no el método y al final nos permite de igual modo realizar una acción.

Una vez que tenemos listo nuestro aspecto el siguiente paso será probarlo, para esto crearemos la siguiente clase:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import com.devs4j.service.HelloWorldService;

@SpringBootApplication
public class Devs4jSpringAopApplication {

	public static void main(String[] args) {
		ConfigurableApplicationContext applicationContext = SpringApplication.run(Devs4jSpringAopApplication.class,
				args);
		HelloWorldService helloWorldService = applicationContext.getBean(HelloWorldService.class);
		helloWorldService.print();
	}

}

Del código anterior podemos analizar los siguientes puntos:

  • Obtenemos un bean del tipo HelloWorldService
  • Ejecutamos el método print()

Salida:

2019-03-29 09:52:40.934  INFO 75349 --- [           main] com.devs4j.Devs4jSpringAopApplication    : Started Devs4jSpringAopApplication in 0.952 seconds (JVM running for 1.265)
2019-03-29 09:52:40.938  INFO 75349 --- [           main] com.devs4j.aop.AroundAdviceExample       : before advice example
2019-03-29 09:52:40.947  INFO 75349 --- [           main] com.devs4j.service.HelloWorldService     : Hello world
2019-03-29 09:52:40.947  INFO 75349 --- [           main] com.devs4j.aop.AroundAdviceExample       : after advice example

Como vemos se imprimió el mensaje before advice example después se imprimió Hello world y al final after advice example esto nos indica que el aspecto que utiliza around advice se ejecuta antes y permite realizar acciones después del método print.

Para estar al pendiente sobre nuestro contenido nuevo síguenos en nuestras redes sociales https://www.facebook.com/devs4j/ y https://twitter.com/devs4j.

Spring framework 5 : AOP After throwing Advice


Como vimos en el post pasado https://devs4j.com/2019/02/28/spring-framework-5-aop-conceptos-basicos/ existen diferentes tipos de advices, en este post nos enfocaremos en After throwing Advice.

Para poder seguir estos ejemplos es necesario crear un proyecto spring boot simple.

Creación de un servicio de spring

El primer paso para entender como funcionan los advices será crear un servicio de spring, este objeto será nuestro Target object.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

/**
 * @author raidentrance
 *
 */
@Service
public class HelloWorldService {

	private static final Logger log = LoggerFactory.getLogger(HelloWorldService.class);

	public void print() {
		log.info("Hello world");
		throw new IllegalStateException();
	}

}

Como vemos nuestro servicio es solo una clase llamada HelloWorldService con un método llamado print().

After throwing Advice

En este ejemplo interceptaremos las peticiones a la clase HelloWorldService en su método print utilizando un After Throwing Advice, veamos el siguiente ejemplo:

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * @author raidentrance
 *
 */
@Aspect
@Component
public class AfterThrowingAdviceExample {
	
	private static final Logger log = LoggerFactory.getLogger(AfterThrowingAdviceExample.class);

	@AfterThrowing("execution(* com.devs4j.service.HelloWorldService.*(..))")
	public void logAfterThrowing(JoinPoint joinPoint) {
		log.info("After throwing example");
	}
}

Del código anterior podemos analizar los siguientes puntos:

  • La clase esta anotada con @Component y @Aspect esto permite a spring identificarlo como un bean y como un aspecto.
  • La anotación @AfterThrowing nos permite utilizar un After throwing advice.
  • Los advices reciben como parámetro un Pointcut el cual define los objetos que serán afectados por el Advice (Explicaremos Pointcut expression language en otro post).
  • El método recibe como parámetro un objeto que implementa la interfaz JoinPoint, esto nos permite acceder a información del JoinPoint que se interceptó.
  • Lo único que hace nuestro aspecto es imprimir el mensaje After throwing example
  • Los Advices After throwing se ejecutan después de que se ejecutó el método interceptado siempre y cuando haya habido una excepción.

Una vez que tenemos listo nuestro aspecto el siguiente paso será probarlo, para esto crearemos la siguiente clase:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import com.devs4j.service.HelloWorldService;

@SpringBootApplication
public class Devs4jSpringAopApplication {

	public static void main(String[] args) {
		ConfigurableApplicationContext applicationContext = SpringApplication.run(Devs4jSpringAopApplication.class,
				args);
		HelloWorldService helloWorldService = applicationContext.getBean(HelloWorldService.class);
		helloWorldService.print();
	}

}

Del código anterior podemos analizar los siguientes puntos:

  • Obtenemos un bean del tipo HelloWorldService
  • Ejecutamos el método print()

Salida:

2019-03-01 12:53:58.076  INFO 76486 --- [           main] com.devs4j.service.HelloWorldService     : Hello world
2019-03-01 12:53:58.078  INFO 76486 --- [           main] c.devs4j.aop.AfterThrowingAdviceExample  : After throwing example
Exception in thread "main" java.lang.IllegalStateException
	at com.devs4j.service.HelloWorldService.print(HelloWorldService.java:21)
	at com.devs4j.service.HelloWorldService$$FastClassBySpringCGLIB$$c594d12f.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
	at com.devs4j.service.HelloWorldService$$EnhancerBySpringCGLIB$$28652767.print(<generated>)
	at com.devs4j.Devs4jSpringAopApplication.main(Devs4jSpringAopApplication.java:16)

Como vemos se imprimió el mensaje After throwing example después de Hello world, esto nos indica que el aspecto que utiliza after throwing advice se ejecuta después del método print debido a que este arroja una IllegalStateException.

Para estar al pendiente sobre nuestro contenido nuevo síguenos en nuestras redes sociales https://www.facebook.com/devs4j/ y https://twitter.com/devs4j.

Autor: Alejandro Agapito Bautista
Twitter: @raidentrance
Contacto:raidentrance@gmail.com

Spring framework 5 : AOP After returning Advice


Como vimos en el post pasado https://devs4j.com/2019/02/28/spring-framework-5-aop-conceptos-basicos/ existen diferentes tipos de advices, en este post nos enfocaremos en After returning Advice.

Para poder seguir estos ejemplos es necesario crear un proyecto spring boot simple.

Creación de un servicio de spring

El primer paso para entender como funcionan los advices será crear un servicio de spring, este objeto será nuestro Target object.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

/**
 * @author raidentrance
 *
 */
@Service
public class HelloWorldService {

	private static final Logger log = LoggerFactory.getLogger(HelloWorldService.class);

	public void print() {
		log.info("Hello world");
	}

}

Como vemos nuestro servicio es solo una clase llamada HelloWorldService con un método llamado print().

After returning Advice

En este ejemplo interceptaremos las peticiones a la clase HelloWorldService en su método print utilizando un After Returning Advice, veamos el siguiente ejemplo:

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * @author raidentrance
 *
 */
@Aspect
@Component
public class AfterReturningAdviceExample {

	private static final Logger log = LoggerFactory.getLogger(AfterReturningAdviceExample.class);

	@AfterReturning("execution(* com.devs4j.service.HelloWorldService.*(..))")
	public void logAfterReturning(JoinPoint joinPoint) {
		log.info("After returning example");
	}

}

Del código anterior podemos analizar los siguientes puntos:

  • La clase esta anotada con @Component y @Aspect esto permite a spring identificarlo como un bean y como un aspecto.
  • La anotación @AfterReturning nos permite utilizar un After returning advice.
  • Los advices reciben como parámetro un Pointcut el cual define los objetos que serán afectados por el Advice (Explicaremos Pointcut expression language en otro post).
  • El método recibe como parámetro un objeto que implementa la interfaz JoinPoint, esto nos permite acceder a información del JoinPoint que se interceptó.
  • Lo único que hace nuestro aspecto es imprimir el mensaje After returning example
  • Los Advices After returning se ejecutan después de que se ejecutó el método interceptado siempre y cuando no haya habido una excepción.

Una vez que tenemos listo nuestro aspecto el siguiente paso será probarlo, para esto crearemos la siguiente clase:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import com.devs4j.service.HelloWorldService;

@SpringBootApplication
public class Devs4jSpringAopApplication {

	public static void main(String[] args) {
		ConfigurableApplicationContext applicationContext = SpringApplication.run(Devs4jSpringAopApplication.class,
				args);
		HelloWorldService helloWorldService = applicationContext.getBean(HelloWorldService.class);
		helloWorldService.print();
	}

}

Del código anterior podemos analizar los siguientes puntos:

  • Obtenemos un bean del tipo HelloWorldService
  • Ejecutamos el método print()

Salida:

2019-03-01 10:57:37.307  INFO 72532 --- [           main] com.devs4j.service.HelloWorldService     : Hello world
2019-03-01 10:57:37.308  INFO 72532 --- [           main] c.d.aop.AfterReturningAdviceExample      : After returning example

Como vemos se imprimió el mensaje After returning example después de Hello world, esto nos indica que el aspecto que utiliza after returning advice se ejecuta después del método print que se invocó de la clase HelloWorldService.

Para estar al pendiente sobre nuestro contenido nuevo síguenos en nuestras redes sociales https://www.facebook.com/devs4j/ y https://twitter.com/devs4j.

Autor: Alejandro Agapito Bautista
Twitter: @raidentrance
Contacto:raidentrance@gmail.com

Spring framework 5 : AOP Before Advice


Como vimos en el post pasado https://devs4j.com/2019/02/28/spring-framework-5-aop-conceptos-basicos/ existen diferentes tipos de advices, en este post nos enfocaremos en Before Advice.

Para poder seguir estos ejemplos es necesario crear un proyecto spring boot simple.

Creación de un servicio de spring

El primer paso para entender como funcionan los advices será crear un servicio de spring, este objeto será nuestro Target object.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

/**
 * @author raidentrance
 *
 */
@Service
public class HelloWorldService {

	private static final Logger log = LoggerFactory.getLogger(HelloWorldService.class);

	public void print() {
		log.info("Hello world");
	}

}

Como vemos nuestro servicio es solo una clase llamada HelloWorldService con un método llamado print().

Before Advice

En este ejemplo interceptaremos las peticiones a la clase HelloWorldService en su método print utilizando un Before Advice, veamos el siguiente ejemplo:

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * @author raidentrance
 *
 */
@Aspect
@Component
public class BeforeAdviceExample {

	private static final Logger log = LoggerFactory.getLogger(BeforeAdviceExample.class);

	@Before("execution(* com.devs4j.service.HelloWorldService.print*(..))")
	public void logBefore(JoinPoint joinPoint) {
		log.info("Before advice example");
	}
}

Del código anterior podemos analizar los siguientes puntos:

  • La clase esta anotada con @Component y @Aspect esto permite a spring identificarlo como un bean y como un aspecto.
  • La anotación @Before nos permite utilizar un Before advice.
  • Los advices reciben como parámetro un Pointcut el cual define los objetos que serán afectados por el Advice (Explicaremos Pointcut expression language en otro post).
  • El método recibe como parámetro un objeto que implementa la interfaz JoinPoint, esto nos permite acceder a información del JoinPoint que se interceptó.
  • Lo único que hace nuestro aspecto es imprimir el mensaje Before advice example

Una vez que tenemos listo nuestro aspecto el siguiente paso será probarlo, para esto crearemos la siguiente clase:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import com.devs4j.service.HelloWorldService;

@SpringBootApplication
public class Devs4jSpringAopApplication {

	public static void main(String[] args) {
		ConfigurableApplicationContext applicationContext = SpringApplication.run(Devs4jSpringAopApplication.class,
				args);
		HelloWorldService helloWorldService = applicationContext.getBean(HelloWorldService.class);
		helloWorldService.print();
	}

}

Del código anterior podemos analizar los siguientes puntos:

  • Obtenemos un bean del tipo HelloWorldService
  • Ejecutamos el método print()

Salida:

2019-03-01 10:35:26.624  INFO 71997 --- [           main] com.devs4j.aop.BeforeAdviceExample       : Before advice example
2019-03-01 10:35:26.632  INFO 71997 --- [           main] com.devs4j.service.HelloWorldService     : Hello world

Como vemos se imprimió el mensaje Before advice example antes de Hello world, esto nos indica que el aspecto que utiliza before advice se ejecuta antes del método print que se invocó de la clase HelloWorldService.

Para estar al pendiente sobre nuestro contenido nuevo síguenos en nuestras redes sociales https://www.facebook.com/devs4j/ y https://twitter.com/devs4j.

Autor: Alejandro Agapito Bautista
Twitter: @raidentrance
Contacto:raidentrance@gmail.com

Spring framework 5 : AOP Conceptos básicos


AOP (Aspect oriented programming) es un paradigma de programación al igual que la POO (Programación orientada a objetos), en la POO el punto principal de la programación es un objeto mientras que en AOP es un aspecto.

Los aspectos nos ayudan a solucionar problemas llamados crosscutting concerns, para poder adentrarnos a esto primero debemos entender algunos conceptos básicos de AOP:

  • Aspect : Un aspecto es una preocupación o funcionalidad que se aplica a multiples clases, el logging es un buen ejemplo.
  • Join point : Un punto durante la ejecución de un programa como la ejecución de un método o el manejo de una excepción, en Spring Aop siempre será la ejecución de un método.
  • Advice : Será la acción a tomar en un join point específico, existen diferentes tipos de advice “around”, “before” y “after”, se pueden considerar como “interceptores” de nuestros join points.
  • Pointcut : Un predicado que junta un conjunto de join points, para definir este predicado se utiliza AspectJ pointcut expression language.
  • Target object : Un objeto advised por uno o más aspectos, como Spring Aop utiliza proxys este siempre será un objeto proxied.
  • Aop proxy : Un objeto creado por el framework Aop para dar el soporte Aop, en Spring Aop se utiliza proxies dinámicos a través de CGLIB.
  • Weaving : Es el enlace entre los aspectos y los objetos, este se puede hacer de diferentes formas, Spring Aop lo hace en tiempo de ejecución.

Tipos de Advices

Como se menciono anteriormente existen diferentes tipos de advices:

  • Before advice : Este advice se ejecuta antes del join point, no tiene la habilidad de detener la ejecución a menos de que arroje una excepción.
  • After returning : Este advice se ejecuta después del join point, no se ejecuta si hay una excepción.
  • After throwing : Este advise se ejecuta si el método termina por una excepción.
  • After finally : Este advise se ejecuta si el método termina su ejecución de forma normal o por una excepción.
  • Around advice : Este advise rodea la ejecución de un método, puede ejecutar su comportamiento antes, después o incluso si se produce una excepción. También es responsable de determinar si quiere o no proceder con la invocación del método.

Around advice es el advice más poderoso pero es el más general, por esto se recomienda utilizar el más especifico para resolver el problema que necesitamos.

Usos prácticos

Algunos usos prácticos para el uso de Spring Aop son :

  • Logging
  • Seguridad
  • Administración de transacciones
  • Monitoreo de performance
  • Caching
  • Manejo de errores

Para estar al pendiente sobre nuestro contenido nuevo síguenos en nuestras redes sociales https://www.facebook.com/devs4j/ y https://twitter.com/devs4j.

Autor: Alejandro Agapito Bautista
Twitter: @raidentrance
Contacto:raidentrance@gmail.com

Spring framework 5 : Bean Aware interfaces


Aware interface significa en español interfaz consciente, este tipo de interfaces actúan como listeners para ciertos eventos que suceden en Spring framework.

Las siguientes son las Aware interfaces en Spring framework:

Aware interfaceRecurso objetivo
BeanNameAwareEl nombre del bean de las instancias configuradas
en el contenedor
BeanFactoryAwareEl bean factory actual a través del cual se invoca el
contenedor
ApplicationContextAwareEl application context actual a través del cual
puedes invocar el contenedor
MessageSourceAwareEl message source a través del cual se pueden
resolver mensajes
ApplicationeventPublisherAwareEl even publisher a través del cual se pueden publicar eventos de la aplicación
ResourceLoaderAwareEl resource loader a través del cual puedes cargar recursos externos
EnvironmentAwareLa instancia de Environment asociada con el ApplicationContext

Las Aware Interfaces definen métodos setters los cuales se invocan por Spring después de que las propiedades de Spring se asignaron pero antes de que los método callback (postConstruct y preDestroy) se invoquen.

Ejemplo utilizando BeanNameAware

Para entender como funcionan las aware interfaces crearemos el siguiente bean:

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class UserService implements BeanNameAware {

	@Value("fakeUser")
	private String user;

	private static final Logger log = LoggerFactory.getLogger(UserService.class);

	@PostConstruct
	public void init() {
		log.info("Post construct callback {}",user);
	}

	@Override
	public void setBeanName(String name) {
		log.info("Being aware of {} {}", name,user);
	}

	@PreDestroy
	public void destroy() {
		log.info("Pre destroy callback");
	}
}

Al ejecutar la aplicación tendremos la siguiente salida:

2019-02-14 16:01:55.319  INFO 16934 --- [           main] com.devs4j.Devs4jSpringCoreApplication   : Starting Devs4jSpringCoreApplication on m-C02RV1WXG8WP with PID 16934 (/Users/maagapi/Documents/workspaces/devs4j/devs4j-spring-core/target/classes started by maagapi in /Users/maagapi/Documents/workspaces/devs4j/devs4j-spring-core)
2019-02-14 16:01:55.321  INFO 16934 --- [           main] com.devs4j.Devs4jSpringCoreApplication   : No active profile set, falling back to default profiles: default
2019-02-14 16:01:55.686  INFO 16934 --- [           main] com.devs4j.aware.UserService             : Being aware of userService fakeUser
2019-02-14 16:01:55.687  INFO 16934 --- [           main] com.devs4j.aware.UserService             : Post construct callback fakeUser
2019-02-14 16:01:55.833  INFO 16934 --- [           main] com.devs4j.Devs4jSpringCoreApplication   : Started Devs4jSpringCoreApplication in 0.816 seconds (JVM running for 1.11)
2019-02-14 16:01:55.836  INFO 16934 --- [       Thread-2] com.devs4j.aware.UserService             : Pre destroy callback

Este tipo de interfaces se utilizan para logging o para realizar integraciones con código legado, en la mayoría de los casos debemos evitar utilizarlas debido a que acoplan nuestra aplicación a Spring framework.

Para estar al pendiente sobre nuestro contenido nuevo síguenos en nuestras redes sociales https://www.facebook.com/devs4j/ y https://twitter.com/devs4j.

Autor: Alejandro Agapito Bautista
Twitter: @raidentrance
Contacto:raidentrance@gmail.com

Spring framework 5 : Spring Expression Language SpEL


Spring expression language (SpEL) es un lenguaje de expresiones que permite realizar operaciones sobre la información en tiempo de ejecución, en el post anterior se utilizó para leer información de un archivo .properties, en este post hablaremos más sobre expression language en detalle.

Los operadores disponibles en SpEL son los siguientes:

Operadores aritmeticos+, -, *, /, %, ^, div, mod
Relacionales <, >, ==, !=, <=, >=, lt, gt, eq, ne, le, ge
Lógicosand, or, not, &&, ||, !
Condicionales?:
Expresiones regularesMatchers

A continuación mostraremos como utilizarlos en una aplicación de spring.

SpelExpressionParser

Antes de iniciar, el primer paso será aprender a utilizar la clase SpelExpressionParser la cual nos permite evaluar expresiones sin necesidad de iniciar el contexto de Spring framework, a continuación se muestra como crearlo:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

/**
 * @author raidentrance
 *
 */
public class SpelExpressionApplication {

	private static final Logger log = LoggerFactory.getLogger(SpelExpressionApplication.class);

	public static void main(String[] args) {
		ExpressionParser expressionParser = new SpelExpressionParser();
		Expression expression = expressionParser.parseExpression("'Hi from devs4j'");
		log.info("String expression {}",expression.getValue());
		
	}
}

Analizando el código anterior podemos ver lo siguiente :

  • SpelExpressionParser nos permite evaluar expresiones de spring SpEL
  • El método Expression parseExpression(String expression) recibe como parámetro una expresión de spring y devuelve un objeto de tipo Expression.
  • La clase Expression contiene un método llamado Object getValue() el cuál devuelve el resultado de la expresión.

Ejemplos básicos de expresiones

Una vez que entendimos como evaluar expresiones SpEL, el siguiente paso será ver algunos ejemplos:

Uso de Strings

public static void main(String[] args) {
	ExpressionParser expressionParser = new SpelExpressionParser();
	Expression expression = expressionParser.parseExpression("'Hi'.concat('from devs4j')");
	log.info("Concat expression {}", expression.getValue());
	expression = expressionParser.parseExpression("'Hi from devs4j'.toUpperCase()");
	log.info("To upper case expression {}", expression.getValue());
	expression = expressionParser.parseExpression("'Hi from devs4j'.length()");
	log.info("Get length expression {}", expression.getValue());

}

La expresión anterior concatena los Strings “Hi” y “from devs4j” al ejecutarlo el resultado será:

11:05:36.022 [main] INFO com.devs4j.spel.SpelExpressionApplication - Concat expression Hifrom devs4j
11:05:36.026 [main] INFO com.devs4j.spel.SpelExpressionApplication - To upper case expression HI FROM DEVS4J
11:05:36.026 [main] INFO com.devs4j.spel.SpelExpressionApplication - Get length expression 14

Operadores aritméticos

private static final Logger log = LoggerFactory.getLogger(SpelExpressionApplication.class);

public static void main(String[] args) {
	ExpressionParser expressionParser = new SpelExpressionParser();
	Expression expression = expressionParser.parseExpression("10 + 20");
	log.info("Arithmetic expression {}", expression.getValue());

	expression = expressionParser.parseExpression("10 - 20");
	log.info("Arithmetic expression {}", expression.getValue());

	expression = expressionParser.parseExpression("10 * 20");
	log.info("Arithmetic expression {}", expression.getValue());

	expression = expressionParser.parseExpression("20 / 10");
	log.info("Arithmetic expression {}", expression.getValue());

	expression = expressionParser.parseExpression("20 mod 10");
	log.info("Arithmetic expression {}", expression.getValue());

	expression = expressionParser.parseExpression("2 ^ 3");
	log.info("Arithmetic expression {}", expression.getValue());

	expression = expressionParser.parseExpression("(2 ^ 3) * 2 + 24");
	log.info("Arithmetic expression {}", expression.getValue());

}

La salida del código anterior sería:

11:17:42.464 [main] INFO com.devs4j.spel.SpelExpressionApplication - Arithmetic expression 30
11:17:42.468 [main] INFO com.devs4j.spel.SpelExpressionApplication - Arithmetic expression -10
11:17:42.469 [main] INFO com.devs4j.spel.SpelExpressionApplication - Arithmetic expression 200
11:17:42.469 [main] INFO com.devs4j.spel.SpelExpressionApplication - Arithmetic expression 2
11:17:42.470 [main] INFO com.devs4j.spel.SpelExpressionApplication - Arithmetic expression 0
11:17:42.470 [main] INFO com.devs4j.spel.SpelExpressionApplication - Arithmetic expression 8
11:17:42.470 [main] INFO com.devs4j.spel.SpelExpressionApplication - Arithmetic expression 40

Operadores relacionales

public static void main(String[] args) {
	ExpressionParser expressionParser = new SpelExpressionParser();
	Expression expression = expressionParser.parseExpression("10 < 20");
	log.info("Relational expression {}", expression.getValue());

	expression = expressionParser.parseExpression("10 > 20");
	log.info("Relational expression {}", expression.getValue());

	expression = expressionParser.parseExpression("10 == 20");
	log.info("Relational expression {}", expression.getValue());

	expression = expressionParser.parseExpression("10 != 20");
	log.info("Relational expression {}", expression.getValue());

}

Salida del código anterior:

11:19:59.557 [main] INFO com.devs4j.spel.SpelExpressionApplication - Relational expression true
11:19:59.561 [main] INFO com.devs4j.spel.SpelExpressionApplication - Relational expression false
11:19:59.562 [main] INFO com.devs4j.spel.SpelExpressionApplication - Relational expression false
11:19:59.562 [main] INFO com.devs4j.spel.SpelExpressionApplication - Relational expression true

Operadores lógicos

public static void main(String[] args) {
	ExpressionParser expressionParser = new SpelExpressionParser();
	Expression expression = expressionParser.parseExpression("100 > 20 && 100 < 10000");
	log.info("Relational expression {}", expression.getValue());

	expression = expressionParser.parseExpression("100 < 20 || 100 < 10000");
	log.info("Relational expression {}", expression.getValue());

	expression = expressionParser.parseExpression("!(100 < 20) ");
	log.info("Relational expression {}", expression.getValue());
}

Salida:

11:22:29.569 [main] INFO com.devs4j.spel.SpelExpressionApplication - Relational expression true
11:22:29.573 [main] INFO com.devs4j.spel.SpelExpressionApplication - Relational expression true
11:22:29.573 [main] INFO com.devs4j.spel.SpelExpressionApplication - Relational expression true

Operadores condicionales

private static final Logger log = LoggerFactory.getLogger(SpelExpressionApplication.class);

public static void main(String[] args) {
	ExpressionParser expressionParser = new SpelExpressionParser();
	Expression expression = expressionParser.parseExpression("(10 ==20) ? 'Hi':'Adios'");
	log.info("Conditional expression {}", expression.getValue());
}

Salida:

11:24:44.866 [main] INFO com.devs4j.spel.SpelExpressionApplication - Relational expression Adios

Uso de expresiones regulares en SpEL

Veamos el siguiente modelo:

class User {
	private String username;
	private String password;

	public User(String username, String password) {
		this.username = username;
		this.password = password;
	}

	// Getters y setters
}
public static void main(String[] args) {

	User user = new User("raidentrance", "devs4jRules");
	
	ExpressionParser expressionParser = new SpelExpressionParser();
	Expression expression = expressionParser.parseExpression("username matches '[a-zA-Z]+'");
	log.info("Regex expression {}", expression.getValue(user));
	
	expression = expressionParser.parseExpression("password matches '[a-zA-Z]+'");
	log.info("Regex expression {}", expression.getValue(user));
}

Salida:

11:37:49.944 [main] INFO com.devs4j.spel.SpelExpressionApplication - Regex expression true
11:37:49.947 [main] INFO com.devs4j.spel.SpelExpressionApplication - Regex expression false

Estos son solo algunos ejemplos sobre el uso de Expression language en Spring, cabe aclarar que es posible utilizarlo también con la anotación @Value(String value) lo cual lo hace un lenguaje muy poderoso y fácil de utilizar en Spring.

Para estar al pendiente sobre nuestro contenido nuevo síguenos en nuestras redes sociales

 https://www.facebook.com/devs4j/ 

https://twitter.com/devs4j.

Autor: Alejandro Agapito Bautista
Twitter: @raidentrance
Contacto:raidentrance@gmail.com