从对象本身获取AOP代理

时间:2011-09-20 09:04:36

标签: spring aop spring-aop

可以在Spring中获取给定对象的代理吗?我需要调用子类的函数。但是,显然,当我直接打电话时,方面不适用。这是一个例子:

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

我找到了实现这一目标的方法。它有效,但我认为不是很优雅:

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

3 个答案:

答案 0 :(得分:14)

这个hack非常尴尬,请考虑重构代码或使用AspectJ编织。您可能会感到警告,这是解决方案

AopContext.currentProxy()

JavaDoc。我在博客上发布了herehere

答案 1 :(得分:13)

Tomasz建议的

AopContext.currentProxy()将起作用。在代理类之外工作的更通用的解决方案是将对象强制转换为org.springframework.aop.framework.Advised并获取.getTargetSource().getTarget()

前者(从代理对象获取真实对象)是你不应该真正需要的东西。另一方面,获取目标代理可能在某些检查现有bean的实用程序类中有用,以便添加某些功能。

答案 2 :(得分:8)

您可以使用bean后处理器在目标bean上设置对代理的引用。它将Spring中的Spring特定内容移动到单个类中。

<强>后处理器

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

<强>上下文

applicationContext.xml注册后处理器。

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

<强>豆

每个bean必须实现SelfReferencingBean告诉后处理器它需要对代理的引用。

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

现在在每个需要通过代理调用自身的bean中实现setProxy

public class MyBean implements SelfReferencingBean {
    MyBean proxy;

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

如果在直接调用方法时不介意将proxy转换为bean的类型,可以将最后一段代码放入bean基类中。由于你正在经历Method.invoke,你甚至不需要演员。

通过一些工作,我打赌这可以转换为注释处理器la @Autowired。想想看,我不记得我是否尝试使用@Autowired本身添加自引用。

public class MyBean implements SelfReferencingBean {
    @Autowired MyBean proxy;
}