3

I'va a ServiceImpl with is annotated with @Service stereotype of Spring and have two methods in it each one is annotated with custom annotations which are intercepted by Spring.

@Service    
public class ServiceImpl implements Service{

       @CustomAnnotation
       public void method1(){
       ...
       }

       @AnotherCustomAnnotation
       public void method2(){
        this.method1();   
        ...
       }
    }
}

Now Spring uses proxy based AOP approach and hence as I'm using this.method1() interceptor for @CustomAnnotation will not able to intercept this call, We used to inject this service in another FactoryClass and in that way we were able to get the proxy instance like -

  @AnotherCustomAnnotation
    public void method2(){
        someFactory.getService().method1();   
        ...
    }

I'm now using Spring 3.0.x, which is the best way to get the proxy instance?

Premraj
  • 7,802
  • 8
  • 45
  • 66

3 Answers3

3

The other alternative is to use AspectJ and @Configurable. Spring seems to be going towards these days (favoring).

I would look into it if you are using Spring 3 as it is faster (performance) and more flexible than proxy based aop.

Adam Gent
  • 47,843
  • 23
  • 153
  • 203
1

Both methods are inside the same proxy, whereas the AOP functionality just enriches calls from the outside (see Understanding AOP Proxies). There are three ways for you to deal with that restriction:

  1. Change your design (that's what I would recommend)
  2. Change proxy type from JDK-proxy to proxy-target-class (CGLib-based subclassing) Nope, that doesn't help, see @axtavt's comment, it would have to be static AspectJ compilation.
  3. Use ((Service)AopContext.currentProxy()).method1() (Works, but is an awful violation of AOP, see the end of Understanding AOP Proxies)
Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • So I should change my design. just because Spring can't do this? – Premraj Feb 23 '11 at 13:09
  • @Premraj That's not a question of can't. It doesn't do it, by design. AOP comes from the outside, and method calls within one object must never depend on it. Also, Spring didn't invent the JDK proxy mechanism. Blame Sun, if you want – Sean Patrick Floyd Feb 23 '11 at 13:14
  • @Sean Patrick Floyd He can do this if he drops proxy based AOP and uses AspectJ. So I don't know if its by design but rather a limitation of proxy aop. – Adam Gent Feb 23 '11 at 13:24
  • @Adam true. Maybe they turned the restrictions into a design :-) – Sean Patrick Floyd Feb 23 '11 at 13:26
  • @Sean: Point 2 is completely wrong, CGLIB proxies are proxies too, internal call wouldn't go through them as well. – axtavt Feb 23 '11 at 13:45
  • @axtavt thanks, I sometimes confuse CGLib proxies with static AspectJ compilation :-) – Sean Patrick Floyd Feb 23 '11 at 13:47
  • 1
    @Premraj M: to defend Spring framework, EJB 3 suffers the same issue. But what is considered a bad design in Spring (using `AopContext.currentProxy()`) is a standard and advised approach in EJB ([getBusinessObject()](http://download.oracle.com/javaee/5/api/javax/ejb/SessionContext.html#getBusinessObject(java.lang.Class))) – Tomasz Nurkiewicz Feb 23 '11 at 14:44
  • May be because Objects shouldn't rely on the aspect environment and thats the whole purpose of AOP – Premraj Feb 23 '11 at 18:22
0

You could make your ServiceImpl class implement the BeanFactoryAware interface, and lookup itself thanks to the provided bean factory. But this is not dependency injection anymore.

The best solution is to put method1 in another service bean, which would be injected in your existing service bean and to which your existing service bean would delegate.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255