Popular Science: Primavera subyacente mejoras introducidas principio de aplicación (IntroductionAdvice)

Hay cinco refuerzo de primavera: BeforeAdvide (pre-potenciación), AfterAdvice (mejora trasera), ThrowsAdvice (mejora anormal), RoundAdvice (mejora surround), IntroductionAdvice (mejora incorporado)

RoundAdvice (Enhanced Surround): es BeforeAdvide (pre-mejora), una combinación AfterAdvice (después del refuerzo) se llama usando la mejora de sonido envolvente.

Las cuatro primeras mejoras son relativamente simples, tenemos que introducir el concepto y principio IntroductionAdvice (introducido mejorada) de.

La introducción del concepto de mejora (Introducción Los consejos) a: una clase Java no implementa la interfaz A, sin modificar la clase de Java, que tiene una función de una interfaz.

1.Cglib lograr la introducción de una mayor

Recuerde, mi propósito no es para decir que el uso de las mejoras introducidas en la primavera (Esto no es mi estilo), sino más bien para explorar la introducción de características mejoradas para lograr el principio subyacente.

public interface IHello {

    public void sayHello();
}

Lo anterior es una función de interfaz, es la necesidad de mejorar las clases CeremonyService, sin tener que cambiar de clase CeremonyService, tiene función de interfaz IHello.

public class CeremenyService {

    public void sayBye() {
        System.out.println("Say bye from Ceremeny.");
    }

}

Para tener este aspecto:

CeremenyService cs;

IHello ih = (IHello) cs;
ih.sayHello();

Esto es, en realidad se convirtió en CeremenyService tipo IHello.

Escribimos un importante interceptores para implementar esta característica.

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import x.y.IHello;

public class IntroInterceptor implements MethodInterceptor, IHello {
        // 实现了IHello增强接口的对象
    private Object delegate;

    public IntroInterceptor() {
        this.delegate = this;
    }

    public IntroInterceptor(Object delegate) {
        this.delegate = delegate;
    }

    @Override
    public void sayHello() {
        System.out.println("Say hello from delegate.");
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Class<?> clz = method.getDeclaringClass();
        if (clz.isAssignableFrom(IHello.class)) {
                // 如果实现了IHello增强接口,则调用实现类delegate的方法
            return method.invoke(delegate, args);
        }
        return methodProxy.invokeSuper(obj, args);
    }
}

Vamos a escribir una clase de prueba.

public static void main(String[] args) {
    Enhancer en = new Enhancer();
    en.setSuperclass(CeremenyService.class);
    en.setInterfaces(new Class[] { IHello.class });
    en.setCallback(new IntroInterceptor());

    CeremenyService cs = (CeremenyService) en.create();
    cs.sayBye();

    IHello ih = (IHello) cs;
    ih.sayHello();
}

en.setInterfaces (nueva Clase [] {IHello.class}); importantes, representa Cglib generado clase de proxy, configurar la interfaz para ser alcanzado.

Así generada Clase clase de proxy, como:public class CeremenyService$$EnhancerByCGLIB$$86859be5 extends CeremenyService implements IHello

salida:

Say bye from Ceremeny.
Say hello from delegate.

Esta es la parte inferior de la famosa introducción de una mayor (Introducción Los consejos) Principio de aplicación.

2. Marco de Primavera interpretación código introducido fuente mejorada

archivo de configuración XML de primavera.

<bean id="ceremonyService" class="x.y.service.CeremonyService" />
<bean id="ceremonyIntroAdvice" class="x.y.advice.CeremonyIntroAdvice" />

<bean id="ceremonyProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="interfaces" value="x.y.IHello"/>                   <!-- 需要动态实现的接口 -->
        <property name="target" ref="ceremonyService"/>                    <!-- 目标类 -->
        <property name="interceptorNames" value="ceremonyIntroAdvice"/>    <!-- 引入增强 -->
        <property name="proxyTargetClass" value="true"/>                   <!-- 代理目标类(默认为 false,代理接口) -->
</bean>

Necesitamos un interceptor personalizado.

import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.DelegatingIntroductionInterceptor;

import x.y.IHello;

@SuppressWarnings("serial")
public class CeremonyIntroAdvice extends DelegatingIntroductionInterceptor implements IHello {

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        return super.invoke(mi);
    }

    @Override
    public void sayHello() {
        System.out.println("Say hello.");
    }

}

En primavera, la introducción de mejoras para lograr, necesidad de heredar de DelegatingIntroductionInterceptor.

Ver DelegatingIntroductionInterceptor invocar el método siguiente clase () de la fuente.

@Override
    public Object invoke(MethodInvocation mi) throws Throwable {
            // 检测是否是引入增强
        if (isMethodOnIntroducedInterface(mi)) {
            // 执行实现了引入增强接口的delegate对象的增强方法
            Object retVal = AopUtils.invokeJoinpointUsingReflection(this.delegate, mi.getMethod(), mi.getArguments());

            // Massage return value if possible: if the delegate returned itself,
            // we really want to return the proxy.
            if (retVal == this.delegate && mi instanceof ProxyMethodInvocation) {
                Object proxy = ((ProxyMethodInvocation) mi).getProxy();
                if (mi.getMethod().getReturnType().isInstance(proxy)) {
                    retVal = proxy;
                }
            }
            return retVal;
        }

        return doProceed(mi);
    }

AopUtils.invokeJoinpointUsingReflection método interno (), de hecho, refleja llamada al método.

try {
    ReflectionUtils.makeAccessible(method);
    return method.invoke(target, args);
}

Por último, escribir un método de prueba para la prueba.

public static void main(String[] args) {

    FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext(
            "D:/workspace/Spring4.2.5/bin/applicationContext.xml");

    CeremonyService service = context.getBean("ceremonyProxy", CeremonyService.class);
    service.sayBye();

    IHello hello = (IHello) service;
    hello.sayHello();

    context.close();
}

salida:

Say bye.
Say hello.

resumen

De alta calidad de la programación de vídeo shangyepingtai.xin

El artículo describe cómo utilizar más, pero menos describe el principio del artículo, yo prefiero introducir el principio del artículo. Espero que este post útil.

Publicados 122 artículos originales · ganado elogios 47 · Vistas a 30000 +

Supongo que te gusta

Origin blog.csdn.net/fengzongfu/article/details/105323962
Recomendado
Clasificación