1

I have written below code in controller.

For this controllerMethod method the aspectj Pointcut expression is working fine but for executeService method Aspect is not working.

@RequestMapping(value = "URL", method = RequestMethod.POST) public ModelAndView controllerMethod(@ModelAttribute ModelAttribute reqModel, HttpServletRequest req, HttpServletResponse res) { try { response = executeService(param1, param2); } catch (Exception e) { } } private ResponseObject executeService(String param1, String param2){ //Code.... } 

I have written the aspect as below.

@Before("execution(* com.*.*.Controller.executeService(..))") public void logBefore(JoinPoint joinPoint) { logger.info("Before aspect: " + joinPoint.getSignature().getName()); } 

Can you please let me know where is the issues. I need to execute aspect before calling executeService method.

4
  • 1
    Spring uses proxies for AOP, only method calls INTO the object are intercepted, internal method calls aren't intercepted. Commented Jun 5, 2017 at 7:11
  • I have changed private method to public. Still not working for me. Commented Jun 5, 2017 at 7:13
  • Add a self controller filed named self with Annotation @Autowire in the code.And call the executeService like 'self.executeService` Commented Jun 5, 2017 at 7:18
  • Read the comment.. Regardless of the modifier it is still an internal method call. Commented Jun 5, 2017 at 8:17

3 Answers 3

2

Because the AOP not intercept internal call ,so you can add a self-controller field,and call the internal method by self.method(...). Following code:

@Controller public class ExampleController{ @Autowired private ExampleController self; @RequestMapping(value = "URL", method = RequestMethod.POST) public ModelAndView controllerMethod(@ModelAttribute ModelAttribute reqModel, HttpServletRequest req, HttpServletResponse res) { try { response = self.executeService(param1, param2); } catch (Exception e) { } } public ResponseObject executeService(String param1, String param2){ //Code.... } } 
Sign up to request clarification or add additional context in comments.

Comments

0

You need to @RequestMapping(value = "URL", method = RequestMethod.POST) direct to executeService then its work.

Comments

0

Although our colleagues have provided correct answers, I'll summarize.

When it comes to aspects implementation, spring generates a proxy that wraps your controller. The proxy is implemented in a way that it has special hooks to invoke aspects before and after the class (or around, altering the flow altogether).

Spring uses two different strategies for proxy generation:

  • java.lang.Proxy based
  • CGLIB based

The first one is in general better, faster but works only with interfaces. The generated proxy is "something" that implements all the methods of the interface. The implementation methods contain those hooks I've talked before, but since the methods are only methods in the interface they have to be public

CGLIB - is slower, but it can work with classes as well (with some restrictions though). The way it works is sub-classing the parent class and overriding the methods provided by the super class. This new method (let's call it foo) will call all the hooks and somewhere in code if needed will call super.foo().

Now, obviously this can't really work with private methods because its impossible to override private methods. That's why my colleagues have pointed that private won't work here.

Now regarding the self injection stuff:

When you're inside the method of original controller and you're trying to call just another method (even if its public), you're not working with proxy any more, you're kind of behind the proxy and work with original class. So this means that you won't be able to take advantage of "enhanced" method.

That's why there is a self injection - you can see (with debugger for example) that the self-injected dependency is actually a dependency with all the proxies, that's why it starts to work.

Another workaround is to refactor the method to another Spring bean, inject this bean to your controller, and provide a definition for that bean.

3 Comments

Self Autowire is also not working as it is throwing error. Not able to find the resource.
Are you on Spring 4.3? Self injection with autowiring is officially supported only in Spring 4.3 which is a pretty new version of spring. An older way is using @Resource annotation. See here stackoverflow.com/questions/5152686/self-injection-with-spring
Ya, I am on old version 3.2. Will change to @Resource annotation.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.