Conceptos

El modelo de corte de Spring permite reutilizar los cortes independientemente del tipo de consejo. Puede orientar diferentes tipos de sugerencias utilizando el mismo segmento.

La interfaz org.springframework.aop.Pointcut es la interfaz central utilizada para orientar los consejos a clases y métodos específicos. A continuación se muestra la interfaz completa:

interfaz pública Pointcut {
    Filtro de clase getClassFilter();
    MétodoMatcher getMethodMatcher();
}

Dividir la interfaz Pointcut en dos partes le permite reutilizar partes de las clases y métodos que se combinan, así como realizar operaciones de composición detalladas (como "unirse" con otro comparador de métodos).

La interfaz ClassFilter se utiliza para restringir el segmento a un conjunto determinado de clases de destino. Si el método matches() siempre devuelve verdadero, entonces todas las clases de destino coinciden. La siguiente lista muestra la definición de la interfaz ClassFilter:

public interface ClassFilter {
    boolean matches(Class clazz);
}

La interfaz MethodMatcher suele ser más importante. A continuación se muestra la interfaz completa:

public interface MethodMatcher {
    boolean matches(Method m, Class<?> targetClass);
    boolean isRuntime();
    boolean matches(Method m, Class<?> targetClass, Object... args);
}

El método matches(Method, Class) se utiliza para comprobar si un segmento determinado coincide con un método determinado en la clase de destino. Este cálculo se puede realizar al crear un proxy AOP para evitar tener que realizar una verificación en cada llamada al método. Si el método matches con dos argumentos devuelve true para un método determinado, y el método isRuntime() devuelve true para un MethodMatcher, se llamará al método de coincidencia con tres argumentos en cada llamada al método. Esto permite que el segmento observe los argumentos pasados a la llamada al método justo antes de que el consejo de destino comience a ejecutarse.

La mayoría de las implementaciones de MethodMatcher son estáticas, lo que significa que su método isRuntime() devuelve false. En este caso, nunca se llama al método matches con tres argumentos.

Si es posible, intente hacer que los sectores sean estáticos permitiendo que el marco AOP almacene en caché los resultados del cálculo del sector al crear el proxy AOP.

Operaciones sobre cortes

Spring admite operaciones (particularmente unión e intersección) en sectores.

Unión significa métodos que son iguales a cualquiera de los sectores. Intersección significa métodos que coinciden con ambos sectores. La fusión suele ser una operación más práctica. Puede componer sectores usando métodos estáticos de la clase org.springframework.aop.support.Pointcuts o usando la clase ComposablePointcut del mismo paquete. Sin embargo, utilizar expresiones de corte de AspectJ suele ser un enfoque más sencillo.

Rebanadores de expresión de AspectJ

A partir de la versión 2.0, el tipo de segmento más importante utilizado por Spring es org.springframework.aop.aspectj.AspectJExpressionPointcut. Esta es una segmentación que utiliza la biblioteca proporcionada por AspectJ para analizar la cadena de expresión de segmentación de AspectJ.

Para obtener más información sobre las primitivas de corte admitidas por AspectJ, consulte el capítulo anterior.

Implementación cómoda de cortes

Spring proporciona varias implementaciones de corte convenientes. Algunos de ellos se pueden utilizar directamente; otros están diseñados para crear subclases en sectores específicos de la aplicación.

Cortes estáticos

Los sectores estáticos se basan en el método y la clase de destino y no pueden tener en cuenta los argumentos del método. Para la mayoría de los casos de uso, los cortes estáticos son suficientes y mejores. Spring solo puede evaluar un segmento estático una vez si se llama al método por primera vez. Después de esto, no es necesario volver a calcular el segmento cada vez que se llama al método.

El resto de esta sección describe algunas de las implementaciones de corte estático que se incluyen con Spring.

Cortes de expresión regular

Una forma obvia de definir sectores estáticos es con expresiones regulares. Varios marcos AOP además de Spring permiten que esto suceda. org.springframework.aop.support.JdkRegexpMethodPointcut es un corte de expresión regular genérico que utiliza el soporte de expresiones regulares del JDK.

Utilizando la clase JdkRegexpMethodPointcut, puede especificar una lista de cadenas de plantilla. Si alguno de ellos coincide, el segmento tomará el valor true. (Como consecuencia, la porción resultante será en realidad una unión de los patrones especificados).

El siguiente ejemplo muestra cómo utilizar

<bean id="settersAndAbsquatulatePointcut"
        class="org.springframework.aop.support.JdkRegexpMethodPointcut">
    <property name="patterns">
        <list>
            <value>.*set.*</value>
            <value>.*absquatulate</value>
        </list>
    </property>
</bean>

Spring proporciona una clase RegexpMethodPointcutAdvisor conveniente que le permite también hacer referencia a Advice (recuerde que Advice puede ser un consejo de "intercepción", un "consejo" antes", consejo "lanzar una excepción" y otros). Detrás de escena, Spring usa JdkRegexpMethodPointcut. El uso de RegexpMethodPointcutAdvisor simplifica la vinculación porque un solo bean encapsula tanto el corte como el consejo, como se muestra en el siguiente ejemplo:

<bean id="settersAndAbsquatulateAdvisor"
        class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
    <property name="advice">
        <ref bean="beanNameOfAopAllianceInterceptor"/>
    </property>
    <property name="patterns">
        <list>
            <value>.*set.*</value>
            <value>.*absquatulate</value>
        </list>
    </property>
</bean>

Puedes utilizar RegexpMethodPointcutAdvisor con cualquier tipo de Advice.

Porciones basadas en atributos

Un tipo importante de segmento estático es el segmento basado en metadatos. Esto utiliza los valores de los atributos de metadatos (normalmente metadatos a nivel de fuente).

Porciones dinámicas

Calcular sectores dinámicos es una tarea que requiere más recursos. Estos sectores tienen en cuenta los argumentos del método, así como la información estática. Esto significa que deben evaluarse cada vez que se llama al método y que el resultado no se puede almacenar en caché porque los argumentos cambiarán.

El ejemplo principal es el segmento control flow.

Controlar porciones de flujo

Los cortes de puntos de flujo de control de Spring son conceptualmente similares a los cortes cflow de AspectJ, aunque no tan eficientes. (Actualmente no hay forma de especificar que un segmento vaya por debajo de un punto de unión que coincida con otro segmento). El segmento de flujo de control coincide con la pila de llamadas actual. Por ejemplo, podría activarse si el punto de conexión fue llamado por un método del paquete com.mycompany.web o de la clase SomeCaller. Los sectores del flujo de control se especifican mediante la clase org.springframework.aop.support.ControlFlowPointcut.

Las porciones de flujo de control son significativamente más caras de calcular en tiempo de ejecución que incluso otras porciones dinámicas. En Java 1.4, el costo es aproximadamente cinco veces mayor que el de otras segmentaciones dinámicas.

Superclases de sectores

Spring proporciona superclases prácticas de segmentación de datos (clases principales) que pueden ayudarle a implementar sus propias segmentaciones.

Java
class TestStaticPointcut extends StaticMethodMatcherPointcut {
    public boolean matches(Method m, Class targetClass) {
        // returns true if specially specified criteria match
    }
}
Kotlin
class TestStaticPointcut : StaticMethodMatcherPointcut() {
    override fun matches(method: Method, targetClass: Class<*>): Boolean {
        // returns true if specially specified criteria match
    }
}

También hay superclases para segmentaciones dinámicas. Puedes utilizar cortes especiales con cualquier tipo de puntas.

Cortes especiales

Debido a que los sectores en Spring AOP son clases de Java y no funciones del lenguaje (como en AspectJ), puede declarar sectores personalizados, ya sean estáticos o dinámicos. Los sectores especiales en Spring pueden ser arbitrariamente complejos. Sin embargo, se recomienda utilizar el lenguaje de expresión de corte AspectJ si es posible.

Las versiones posteriores de Spring pueden brindar soporte para el "corte semántico" como se propone en JAC, por ejemplo, "cualquier método que modifique las variables de instancia en el objeto de destino".