Popular Science: Primavera subjacente melhorias introduzidas princípio de implementação (IntroductionAdvice)

Existem cinco reforço da mola: BeforeAdvide (pré-reforço), AfterAdvice (reforço traseiro), ThrowsAdvice (aumento anormal), RoundAdvice (reforço envolvente), IntroductionAdvice (reforço incorporados)

RoundAdvice (Enhanced Surround): é BeforeAdvide (pré-realce), uma combinação AfterAdvice (post-boost) é chamado usando o reforço surround.

As quatro primeiras melhorias são relativamente simples, temos de introduzir o conceito e princípio IntroductionAdvice (introduzido avançado) de.

Introduzindo o conceito de avançado (Introdução Advice) para: uma classe Java não implementa a interface A, sem modificar classe Java, que tem uma função de interface A.

1.Cglib conseguir a introdução de reforçada

Lembre-se, meu propósito não é dizer-lhe como usar aprimoramentos introduzidos na Primavera (Este não é o meu estilo), mas sim para explorar a introdução de recursos avançados para alcançar o princípio subjacente.

public interface IHello {

    public void sayHello();
}

A descrição acima é uma função de interface, é a necessidade de reforçar as classes CeremonyService, sem alterar classe CeremonyService, tem a função de interface IHello.

public class CeremenyService {

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

}

Para ter esta aparência:

CeremenyService cs;

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

Ou seja, CeremenyService realmente se transformou em tipo IHello.

Nós escrevemos um importante interceptores para implementar este recurso.

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 escrever uma classe de teste.

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 (nova classe [] {IHello.class}); importantes, representa cglib gerado classe de proxy, definir a interface para ser conseguida.

Assim gerado Classe classe de proxy, como:public class CeremenyService$$EnhancerByCGLIB$$86859be5 extends CeremenyService implements IHello

saída:

Say bye from Ceremeny.
Say hello from delegate.

Esta é a base da famosa introdução de (Advice Introdução) princípio implementação reforçada.

2. framework Spring interpretação código introduzido fonte melhorada

arquivo de configuração XML do Spring.

<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>

Precisamos de um 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.");
    }

}

Na Primavera, a introdução de melhorias para conseguir, precisa herdar de DelegatingIntroductionInterceptor.

Veja DelegatingIntroductionInterceptor invocar o método seguinte classe () da fonte.

@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);
    }

método interno AopUtils.invokeJoinpointUsingReflection (), na verdade, reflete chamada de método.

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

Finalmente, escrever um método de teste para teste.

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();
}

saída:

Say bye.
Say hello.

resumo

Alta qualidade shangyepingtai.xin programação de vídeo

O artigo descreve como usar mais, mas menos descreve o princípio do artigo, eu prefiro a introduzir o princípio do artigo. Espero que este post útil.

Publicado 122 artigos originais · ganhou elogios 47 · vê 30000 +

Acho que você gosta

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