Obtenir un proxy AOP à partir de l'objet lui-même

Est possible pour obtenir le proxy d'un objet donné au Printemps? J'ai besoin d'appeler une fonction d'une sous-classe. Mais, évidemment, quand je fais un appel direct, les aspects ne sont pas appliquées. Voici un exemple:

public class Parent {

    public doSomething() {
        Parent proxyOfMe = Spring.getProxyOfMe(this); // (please)
        Method method = this.class.getMethod("sayHello");
        method.invoke(proxyOfMe);
    }
}

public class Child extends Parent {

    @Secured("president")
    public void sayHello() {
        System.out.println("Hello Mr. President");
    }
}

j'ai trouvé un moyen d'y parvenir. Cela fonctionne, mais je pense que ce n'est pas très élégant:

public class Parent implements BeanNameAware {

    @Autowired private ApplicationContext applicationContext;
    private String beanName; // Getter

    public doSomething() {
        Parent proxyOfMe = applicationContext.getBean(beanName, Parent.class);
        Method method = this.class.getMethod("sayHello");
        method.invoke(proxyOfMe);
    }
}
18
demandé sur sinuhepop 2011-09-20 13:04:35

3 réponses

ce hack est extrêmement embarrassant, s'il vous plaît envisager de reconfigurer votre code ou en utilisant AspectJ tissage. Vous pouvez vous sentir avertis, voici la solution

AopContext.currentProxy()

JavaDoc . J'ai blogué à ce sujet ici et ici .

13
répondu Tomasz Nurkiewicz 2011-09-20 09:18:55

AopContext.currentProxy() comme suggéré par Tomasz fonctionnera. Une solution plus générique, qui fonctionnera en dehors de la classe proxied est de lancer l'objet à org.springframework.aop.framework.Advised et obtenir .getTargetSource().getTarget()

le PREMIER (obtenir l'objet réel à partir de l'objet proxy) est quelque chose dont vous ne devriez pas vraiment avoir besoin. D'autre part l'obtention de la cible procuration peut être utile dans certaines classe utilitaire qui inspecte les haricots existants afin d'ajouter certaines fonctionnalités.

13
répondu Bozho 2011-09-20 09:18:40

vous pouvez utiliser un post-processeur de haricot pour définir une référence au proxy sur le haricot cible. Il déplace les caractéristiques de printemps de vos haricots à une seule classe.

Post-Processeur

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class SelfReferencingBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof SelfReferencingBean) {
            ((SelfReferencingBean) bean).setProxy(bean);
        }
        return bean;
    }
}

contexte

Enregistrer le post-processeur dans applicationContext.xml .

<bean id="srbpp" class="SelfReferencingBeanPostProcessor"/>

haricots

chaque haricot doit implémenter SelfReferencingBean pour dire au post-processeur qu'il a besoin d'une référence au proxy.

public interface SelfReferencingBean {
    void setProxy(Object proxy) ;
}

implémente maintenant setProxy dans chaque haricot qui doit s'appeler par son intermédiaire.

public class MyBean implements SelfReferencingBean {
    MyBean proxy;

    @Override
    public void setProxy(Object proxy) {
        this.proxy = (MyBean) proxy;
    }
}

vous pouvez mettre ce dernier morceau de code dans une classe de base de haricot si vous ne vous gênez pas de lancer proxy au type de haricot lors de l'appel de méthodes directement sur elle. Puisque vous traversez Method.invoke vous ne le feriez pas même plus besoin de la fonte.

avec un peu de travail je parie que cela pourrait être converti en un processeur d'annotation a la @Autowired . En y repensant, je ne me souviens même pas si j'ai essayé d'ajouter une référence personnelle en utilisant @Autowired lui-même.

public class MyBean implements SelfReferencingBean {
    @Autowired MyBean proxy;
}
6
répondu David Harkness 2012-06-30 21:41:39