Announcement Announcement Module
Collapse
No announcement yet.
Can I use a MethodInterceptor with a non Spring instantiated class? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Can I use a MethodInterceptor with a non Spring instantiated class?

    Hi,

    I am trying to get to grips with AOP.

    What I would like to do is get my MethodInterceptor to be invoked on instances coming out of Hibernate.

    So, I have an interface Person and a class PersonImpl. Neither of these is mentioned in my spring app context .xml. When I go through my DAO (created by Spring and containing the HibernateSessionFactory, also created by Spring) to get my person instance, I would like the MethodInterceptor I have written to be invoked when something calls getName (or whatever) on the person instance. Is this possible at all? I have read through docs and tried to find examples, but everything seems to talk only about aop and objects living in the Spring context.

    I have tried all sorts of things and eventually got the breakpoint in my MethodInterceptor to be called but only for objects created in the Spring context - but I can't even recreate that now!

    All help gratefully received.

  • #2
    You need AspectJ for this kind of cases...

    Since you want to crosscut your domain objects that not managed by Spring, you will need to weave in AspectJ aspects. You can use either compile-time or load-time weaving (LTW). Please check the Spring documentation or AspectJ documentation (http://eclipse.org/aspectj) for more info.

    -Ramnivas

    Comment


    • #3
      aspectJ?

      I recently tried working with AspectJ (just to try it out), and it is indeed powerful.
      A search on monster.com yields < 10 jobs matching aspectj or "aspect j" however.
      I read on the www.eclipse.org/aspectj site that it is "a seamless aspect-oriented extension to the Java programming language"
      - but it is an extension.

      I'm wondering how others feel about using it.

      Comment


      • #4
        Using AspectJ gives you competitive advantage

        I am clearly biased, but AspectJ is used quite significantly in many places. Just see some of the replies in http://www.theserverside.com/news/th...hread_id=39026 to see all the places AspectJ is used. The job market will eventually catch on, since either internal champions or external consultants do most of the current implementations.

        The bottom line is you have to take care of crosscutting concerns somehow, which are likely to cause code scattering throughout your code base. AspectJ happens to provide an elegant solution for those kinds of problems.

        -Ramnivas

        Comment


        • #5
          You need to programmatically create the proxy to wrap your domain object in your DAO:
          Code:
          ProxyFactoryBean proxyFactory = (ProxyFactoryBean) ctx.getBean("&person");
          proxyFactory.setSingleton(false);
          synchronized (proxyFactory) {
              proxyFactory.setTarget(hibernatePerson);
              return (Person) proxyFactory.getObject();
          }
          Note that you'll get a warning from Spring each time this code is executed because when proxy factory is non-single, the target should be set by name instead of by instance.

          If you want to decouple your DAO impl from Spring APIs. You can define a method:
          Code:
          public Person wrapPerson(Person person) {
              return person;
          }
          Then use arbitrary method replacement to implement the above code.

          I haven't tried this in reality. So you need to try by yourself.

          Good luck!

          Comment


          • #6
            Another way you can achieve this is to use Jakarta Commons BeanUtils in your DAO implementation to copy properties from the instance instantiated by Hibernate to the instance obtained from Spring before you return the Spring-managed instance.

            Then again, your interceptor will intercept the setter methods used during copying.

            You may want to cast the object to Advised and manipulate the interceptors so that these setter methods are not intercepted during the copying.

            Good luck.

            Comment


            • #7
              Seabludude,

              Thanks for your reply. I had already thought of this, but it won't do everything I want. I should also have said that a Person has a Job (or whatever) which is retrieved by Hibernate when the person is retrieved. I would like my MethodInterceptor to be invoked when methods on the Job are called too.

              I suppose I could go through my object map, e.g. person.getJob().getJobLocation(). get whatever and do the same thing you suggest for all instances, but then I lose the benefit of the lazy loading which i need in my app. When I go to get all 5000 Person objects, I would like it and all the other objects retrieved to be ready to go with the MethodInterceptor without having to do any iterations.

              I am currently looking at AspectJ and it does indeed appear to be a very powerful beast. However, I don't think I've really got the time right now to learn how to tame the beast - deadlines and all...

              Comment


              • #8
                Rained,

                Depends on what you want to do in the interceptor...

                If you don't mind doing those in your PersonImpl class, you can try domain object dependency injection.

                Basically, your DAO implementation needs to be application context-aware and for each Person instance returned by Hibernate, do this:
                ((AbstractApplicationContext) context).getAutowireCapableBeanFactory().autowireB eanProperties(person, AUTOWIRE_BY_TYPE, true);

                Alternatively, you can do this by register a Hibernate load listener...

                Comment

                Working...
                X