2
votes

I have following aspect class:

@Component
@Aspect
public class LoggedRequestAspect {

    private static final Logger LOG = LoggerFactory.getLogger(LoggedRequestAspect.class);

    @Before("com.application.aspect.pointcut.LoggedRequestPointCut.LogRequest()")
    public void logRequest(){
        System.out.println("Method Executed!");
        LOG.debug("Method Executed!");
    }
}

And for Annotation class:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LoggedRequest {
}

And finally pointcut:

public class LoggedRequestPointCut {

    @Pointcut("execution(@com.application.aspect.annotation.LoggedRequest * *(..))")
    public void LogRequest(){}

}

Now for sure, I have annotated the required api method in my controller:

...
    @LoggedRequest
    @RequestMapping(value = "/login", method = { RequestMethod.POST })
    public @ResponseBody Map<String, Object> login(/* Param List*/){

...
    }

As suggested by many other answers on SO. I have added following to my spring configuration:

<context:annotation-config/>
...
<context:component-scan base-package="com.application.core"/>
...
<aop:aspectj-autoproxy />

Now All this is not working. I mean on my API call of /login the required advice is not executing.

2
And WHERE have you added <aop:aspectj-autoproxy />? Because if that tis in your root application context (i.e. ContextLoaderListener) it is going to do exactly nothing for your controllers. Next to that you would have to enable proxy-target-class="true" on the <aop:aspectj-autoproxy /> as well to make it work for controllers. - M. Deinum
Try to change from: @Pointcut(execution(@com.application.aspect.annotation.LoggedRequest * *(..)) to @Pointcut(@annotation(com.application.aspect.annotation.LoggedRequest)) and then try to invoke your annotated methods. - mlewandowski
Do you have spring-aop and aspectjweaver in your classpath? - MichaƂ Kosmulski
@M.Deinum Yes I have placed it in my root application context. Where should I put it otherwise? - Tariq
In the context that is loaded by the DispatcherServlet. AOP only works on beans in the same application context not on beans in parent or child contexts. - M. Deinum

2 Answers

2
votes

When using AOP on beans in Spring that is only applied to beans in the same application context.

In a typical web application you would have a ContextLoaderListener and a DispatcherServlet both of which create an ApplicationContext. The ContextLoaderListener creates the so called root application context and the DispatcherServlet a child context with a relation to the root context.

AOP configuration from the root doesn't influence beans in the child context and AOP configuration in the child context doesn't influence beans in the root context.

Now you have configured the aspect and <aop:aspectj-autoproxy /> in the root context and except it to work for a bean that lives in the child context. That obviously isn't going to work. Move (or duplicate) that configuration into the child context.

Another thing is you will need class based proxies as yu don't have an interface, so you probably also want to add proxy-target-class="true" to the <aop:aspectj-autoproxy /> element.

0
votes

it all seems ok, but you should write a thing like this:

<aop:aspectj-autoproxy >
        <aop:include name="loggedRequestAspect"/>
    </aop:aspectj-autoproxy>

because with this final configuration you say at the spring autoproxy infrastructure what beans consider in the auto proxying process. The key point hear is if you want use the aspect for log the method call, it is fine but if you want use the aspect for log the http call it will be not work, in this case could be a good choice use an interceptor.

You may use a your org.springframework.web.servlet.HandlerInterceptor or org.springframework.web.context.request.WebRequestInterceptor implementations

and then register it in a org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter like this:

@Configuration
class MyWebConfiguratio extends WebMvcConfigurerAdapter {
....
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new HandlerInterceptor() {
               ...
            }).addPathPatterns("....");
            registry.addInterceptor(new WebMvcConfigurerAdapter() {
              ....
            }).addPathPatterns("....");
        }

      ....
}

in java config or

 <mvc:interceptors>
        <bean id="localeChangeInterceptor"
              class="com.yourapp.Interceptor""/>
    </mvc:interceptors>

in your xml configuration file with the mvc namespace

I hope this can help you