Announcement Announcement Module
Collapse
No announcement yet.
Accessing the TargetSource from a MethodInterceptor Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Accessing the TargetSource from a MethodInterceptor

    Is there any way to access the TargetSource for a proxied object within the interceptor? In my case, I want to change the target object with a HotSwappableTargetSource:

    Code:
    public class AnInterceptor implements MethodInterceptor  {
        public Object invoke(MethodInvocation methodInvocation) throws Throwable {
            Advised bean = (Advised) something;//where do I get the advised object?
            HotSwappableTargetSource source = (HotSwappableTargetSource) bean.getTargetSource();
            source.swap(somethingElse);
             ...
    }
    methodInvocation.getThis() isn't returning the proxy, but the advised object, and I can't figure out where else I could possibly access the proxy. Any ideas? Or I am going about this the wrong way?

  • #2
    Maybe http://forum.springframework.org/showthread.php?t=17039 might help you.

    Regards,
    Andreas
    Last edited by robyn; May 15th, 2006, 06:54 PM.

    Comment


    • #3
      Originally posted by Andreas Senft
      Maybe http://forum.springframework.org/showthread.php?t=17039 might help you.

      Regards,
      Andreas
      Unfortunately, I don't seem to have access to the proxy, only the target itself.
      Last edited by robyn; May 15th, 2006, 06:53 PM.

      Comment


      • #4
        How about this blog entry

        Comment


        • #5
          Ah, that's a good idea. He's configured Spring to directly provide the Target Source to the Interceptor via IoC. Now, in my case, the target is not a singleton, so I'd imagine that my target source can't be a singleton, either. How do I ensure that each interceptor gets a reference to the target source used by the proxied object?

          Code:
          <bean id="aProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
                  <property name="targetSource" ref="swapper"/>
                  <property name="singleton">
                      <value>false</value>
                  </property>
                  <property name="interceptorNames">
                      <list>
                          <value>anInterceptor</value>
                      </list>
                  </property>
              </bean>
          
              <bean id="swapper" class="org.springframework.aop.target.HotSwappableTargetSource" singleton="false">
                  <constructor-arg>
                      <bean class="path.to.advised.class" singleton="false"/>
                  </constructor-arg>
              </bean>
          
              <bean id="anInterceptor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
                  <constructor-arg>
                      <bean class="path.to.Pointcut"/>
                  </constructor-arg>
                  <constructor-arg>
                      <bean class="path.to.AnInterceptor">
                          <property name="targetSource">
                              <ref bean="swapper"/>
                          </property>
                      </bean>
                  </constructor-arg>
              </bean>
          Edit: Sorry, didn't finish my thought before posting. If I configure things as above, the Interceptor will get a different target source from the proxy, because the target source isn't a singleton. However, if I were to make the target source a singleton, then all of my proxies would share the same target, whichs mean I could only proxy one instance of the advised class. So, how can I ensure that each proxy gets a unique target source, while ensure that each interceptor gets the same target source as its proxy?

          Comment


          • #6
            You can get the current proxy for the advised invocation by calling AopContext.currentProxy. The proxy object can then be cast to an instance of Advised and from there you can retreive the TargetSource using getTargetSource().

            Rob

            Comment


            • #7
              Ok, that worked, thanks, but there is a small problem. The swap doesn't take effect for the current method invocation, only the subsequent ones(in other words, when I call methodInvocation.proceed() after swapping the target, the method is still called on the old target, not the new one). I can get around this by doing:

              methodInvocation.getMethod().invoke(newTarget, methodInvocation.getArguments());

              instead of methodInvocation.proceed(). I only have the one interceptor, so everything will work properly in this case, but it would be nice to know if there was a way to have methodInvocation.proceed() act on the new target after swapping.

              Comment


              • #8
                Mmm, so what you are saying is that you swap the target in the interceptor, but for the whole of that invocation that swap is not active?

                Can you post a feature request for this on JIRA along with a test to highlight it?
                Rob

                Comment


                • #9
                  I will post that JIRA request as soon as I get some time to write a test case. In the meantime, I've found a slightly better solution to the problem than
                  Code:
                  methodInvocation.getMethod&#40;&#41;.invoke&#40;newTarget, methodInvocation.getArguments&#40;&#41;&#41;;
                  is
                  Code:
                  methodInvocation.getMethod&#40;&#41;.invoke&#40;proxy, methodInvocation.getArguments&#40;&#41;&#41;;
                  In the first case, interceptors in the chain after the swapping interceptor will not be executed. In the second case, interceptors in the chain before the swapping interceptor(including the swapping intercetor) will be executed twice, but the interceptors after the swapping interceptor will be executed.

                  Comment


                  • #10
                    Excellent thread... quick question

                    In your last response, you changed newTarget to proxy (in order to avoid the last problem described, which I am also facing). How do you set the proxy Object? Thanks!

                    Comment


                    • #11
                      Do you mean, how do you get the proxy? I got it using AopContext.currentProxy().

                      Comment


                      • #12
                        Thanks...

                        A little introduction to my situation:

                        I am facing the same problem that you had, but instead of swapping the target, I just needed to modify the method arguments. I created a PreInterceptor, where I have the following code:

                        Object[] arguments = invocation.getArguments();
                        Class object = (Class) arguments[0];
                        object.setProperty = false;
                        Advised advised = (Advised) AopContext.currentProxy();
                        Object proxy = (Object) AopContext.currentProxy();
                        Object target = (Object) advised.getTargetSource().getTarget();
                        arguments[0] = object;

                        //return invocation.getMethod().invoke(target,arguments);
                        return invocation.getMethod().invoke(proxy,arguments);

                        Note: I changed the actual Class, object and setProperty to generic words for the sample code.

                        If I use "target" in the invoke method, the postInterceptor is skipped (which is what you found). If I use "proxy", it gets into a loop, calling the PreInterceptor over and over... Any ideas?

                        Thanks in advance for your help

                        Comment


                        • #13
                          I seem to recall that I wrote an interceptor that modified the arguments, and just calling methodInterceptor.proceed() worked properly.

                          Comment

                          Working...
                          X