Announcement Announcement Module
Collapse
No announcement yet.
Simple concept question: intercept multi-thread method? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Simple concept question: intercept multi-thread method?

    Can I intercept method under multi-thread computing?

    Example:
    I have an public method analyze(). It is OK to intercept this method and I see the log.

    Then I add another public method asyncAnalyze() --

    public void asyncAnalyze() {
    Thread t = new Thread(new Runnable() {
    public void run() {
    analyze();
    }
    });

    t.start();
    }

    Funny thing is: when I call asyncAnalyze(), which calls analyze() indirectly, it runs fine but I didn't see any log. It's like analyze() is not intercepted if a call is from inner-class/multi-thread?

    My question is: How can I intercept analyze() in multi-thread?

    Thanks for the help!

  • #2
    Doesn't look like multi-threading issue

    How are you intercepting? Using Spring AOP or AspectJ?

    It doesn't look like a multi-threading issue. Modify your program as follows and I think you will see the same behavior:
    Code:
    public void asyncAnalyze() {
        Runnable r = new Runnable() {
            public void run() {
                analyze();
           }
       };	
       r.run();
    }

    Comment


    • #3
      Find the answer in another reply.

      For anyone in same situation: it is impossible because Spring AOP doesn't intercept a call from the same instance.

      Comment


      • #4
        This is a known problem when using the decorator pattern (which Spring AOP uses); the class that is being decorated has no knowledge of the decorator. If you are using the ProxyFactoryBean you can call setExposeProxy to true and then access it via http://www.springframework.org/docs/...opContext.html

        If you are using LTW or compile time weaving then ignore this post

        Comment


        • #5
          Can you post a link?

          @marmot101

          You find the answer in an other reply.
          Can you post a link to that reply please?

          Jörg

          Comment


          • #6
            bellmann29,

            Sorry that I cannot find that topic. But the basic idea is: Spring AOP doesn't support interception from a function in the same class. It is definitely under this AOP category.

            Comment


            • #7
              Originally posted by marmot101
              But the basic idea is: Spring AOP doesn't support interception from a function in the same class. It is definitely under this AOP category.
              As I mentioned in my reply a couple of replies ago, Spring AOP *does* support interception from a function in the same class, you just need to do a bit more to get it to work.

              The fundamental problem is that Spring uses a decorator, in the form of a runtime generated proxy to execute the interceptors (transactional, logging etc.), this effectively means that there are two classes, the generated proxy and your "target" class. The target class has no knowledge of the proxied class, and thus when it calls methods on itself it is completely bypassing the proxy. You can make the target class aware of the proxy by using the AopContext class (http://www.springframework.org/docs/...opContext.html).

              To put it simply, Spring does the following:

              Code:
              public class MyClass {
                public void myFirstMethod() {
                  mySecondMethod();
                }
              
                public void mySecondMethod() {
                }
              }
              
              public class ProxyGeneratedBySpringWhichLooksLikeMyClass {
                private final MyClass delegate;
                private final List interceptors;
                public ProxyGeneratedBySpringWhichLooksLikeMyClass (
                                   MyClass myClass,
                                    List interceptors
                                   ) {
                  this.delegate = myClass;
                  this.interceptors = interceptors;
                }
              
                public void myFirstMethod() {
                  runInterceptors();
                  delegate.myFirstMethod();
                }
              
                public void mySecondMethod() {
                  runInterceptors();
                  delegate.mySecondMethod()
                }
              }
              The spring container will then do something like:

              Code:
                MyClass myClass = new ProxyGeneratedBySpringWhichLooksLikeMyClass(
                                 new MyClass(),
                                 interceptors);

              So when clients call myClass.myFirstMethod() they are actually talking to the runtime generated proxy, however, if myFirstMethod() calls mySecondMethod() the call to mySecondMethod will *not* go through the proxy.

              PLEASE(!!!) do not take the above code too seriously as Spring offers far more functionality, but hopefully it demonstrates the point.

              Also note that this is completely irrelevant if you are using compile time weaving which doesn't use a decorator/proxy but modifies the byte code directly.

              Comment


              • #8
                Thanks Colin to clear things up. But I think the power of Spring is its unintrusiveness. If I make class aware of AOPContext, I'd rather make function call directly, i.e. call log4j to log the message instead of letting AOP do it.

                My intention is: write program as independent as possible. When I introduce AOPContext into business logic layer, it will prevent me to easily port to other situations.

                However, thanks for explaining the details, that make things clear -- especially from a Spring team member, I really appreciated.

                Best Regards.

                Comment


                • #9
                  Originally posted by marmot101
                  ...
                  My intention is: write program as independent as possible. When I introduce AOPContext into business logic layer, it will prevent me to easily port to other situations.
                  ...
                  In this case you are bound to use "true" AOP product, e.g. AspectJ.

                  Comment


                  • #10
                    Originally posted by marmot101
                    My intention is: write program as independent as possible. When I introduce AOPContext into business logic layer, it will prevent me to easily port to other situations.
                    This is a very good point.

                    There are a number of more elegant solutions that I can think of, but I haven't really got time ATM to go into detail.

                    Essentially, instead of calling this.doSomething() call getThis().doSomething() and then provide a setThis(MyBean). You could then write a BeanPostProcessor to find all beans that implement a setThis and inject the bean back into itself.

                    Code:
                      public class DefaultMyService implements MyService {
                        private MyService decoratedThis;
                    
                        public void doFirstMethod() {
                          ////
                          getThis().doSecondMethod();
                        }
                    
                        public void doSecondMethod() {
                        }
                    
                        private MyService getThis() {
                          return this.decoratedThis;
                        }
                        private void setThis(MyService myService) { 
                          this.decoratedThis = myService;
                        }
                    
                      }
                    This means it isn't dependent on AOP, can be easily unit tested etc. I will leave the BeanPostProcessor up to you

                    I will blog about this when I have more time.

                    Comment


                    • #11
                      Just as addition to the solution described by Colin, see this thread. It also contains an example for the application context.

                      Regards,
                      Andreas

                      Comment


                      • #12
                        Originally posted by Andreas Senft
                        Just as addition to the solution described by Colin, see this thread. It also contains an example for the application context.

                        Regards,
                        Andreas
                        Hey Andreas! You know what they say, "great minds think alike", but then they also say "fools seldom differ". Not sure which category I fall in

                        I would suggest that my BeanPostProcessor solution is a little more elegant (and safer) than implementing FactoryBeanAware (or ApplicationContextAware) and InitialisingBean simply because if the bean is a prototype you then setThis will be called with a different instance, which is absolutely what you do not want

                        I really must blog this...time and all that.

                        Comment


                        • #13
                          Originally posted by yatesco
                          Hey Andreas! You know what they say, "great minds think alike", but then they also say "fools seldom differ". Not sure which category I fall in
                          ...or I

                          Originally posted by yatesco
                          I would suggest that my BeanPostProcessor solution is a little more elegant (and safer) than implementing FactoryBeanAware (or ApplicationContextAware) and InitialisingBean simply because if the bean is a prototype you then setThis will be called with a different instance, which is absolutely what you do not want
                          I agree. Only wondering, where I suggested implementing FactoryBeanAware? I guess you refer to my explicit usage of ProxyFactoryBean. In that case, yes, for prototypes it would be a problem.


                          Originally posted by yatesco
                          I really must blog this...time and all that.
                          Yes, that would really be a good topic.

                          Regards,
                          Andreas

                          Comment


                          • #14
                            Originally posted by Andreas Senft
                            I agree. Only wondering, where I suggested implementing FactoryBeanAware? I guess you refer to my explicit usage of ProxyFactoryBean. In that case, yes, for prototypes it would be a problem.
                            I am not sure who referred to it, someone mentioned (I also mentioned this as well) that if your bean implemented FactoryBeanAware/ApplicationContextAware it could then do a
                            Code:
                            setApplicationContext(ApplicationContext ctx) { this._decoratedThis = ctx.getBean(getBeanName()) }
                            etc. but this absolutely ties you down to spring and you need to implement BeanNameAware, ApplicationContextAware and InitialisingBean!

                            Comment

                            Working...
                            X