Get AOP proxy from the object itself

后端 未结 3 499
伪装坚强ぢ
伪装坚强ぢ 2020-11-27 15:13

Is possible to get the proxy of a given object in Spring? I need to call a function of a subclass. But, obviously, when I do a direct call, the aspects aren\'t applied. Here

相关标签:
3条回答
  • 2020-11-27 15:24

    AopContext.currentProxy() as suggested by Tomasz will work. A more generic solution, that will work outside of the proxied class is to cast the object to org.springframework.aop.framework.Advised and get .getTargetSource().getTarget()

    The former (getting the real object from the proxied object) is something that you should not really need. On the other hand getting the target proxy might be useful in some utility class that inspects existing beans in order to add some feature.

    0 讨论(0)
  • 2020-11-27 15:34

    You can use a bean post-processor to set a reference to the proxy on the target bean. It moves the Spring-specifics from your beans to a single class.

    Post-Processor

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

    Context

    Register the post-processor in applicationContext.xml.

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

    Beans

    Each bean must implement SelfReferencingBean to tell the post-processor that it needs a reference to the proxy.

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

    Now implement setProxy in each bean that needs to call itself through its proxy.

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

    You could put this last bit of code into a bean base class if you don't mind casting proxy to bean's type when calling methods directly on it. Since you're going through Method.invoke you wouldn't even need the cast.

    With a little work I bet this could be converted to an annotation processor a la @Autowired. Come to think of it, I don't recall if I even tried adding a self-reference using @Autowired itself.

    public class MyBean implements SelfReferencingBean {
        @Autowired MyBean proxy;
    }
    
    0 讨论(0)
  • 2020-11-27 15:40

    This hack is extremely awkward, please consider refactoring your code or using AspectJ weaving. You may feel warned, here is the solution

    AopContext.currentProxy()
    

    JavaDoc. I blogged about it here and here.

    0 讨论(0)
提交回复
热议问题