【问题标题】:Get AOP proxy from the object itself从对象本身获取 AOP 代理
【发布时间】:2011-11-20 21:53:24
【问题描述】:

是否可以在 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);
    }
}

【问题讨论】:

标签: spring aop spring-aop


【解决方案1】:

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

AopContext.currentProxy()

JavaDoc。我在 herehere 上写了博客。

【讨论】:

  • 谢谢,成功了!我在我的配置中添加了 。无论如何,我正在阅读以尝试使用 AspectJ。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    您可以使用 bean 后处理器在目标 bean 上设置对代理的引用。它将 Spring-specifics 从您的 bean 移动到单个类。

    后处理器

    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,您甚至不需要演员表。

    我敢打赌,我打赌这可以转换为注释处理器,例如@Autowired。想想看,我什至不记得我是否尝试过使用 @Autowired 本身添加自我引用。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多