2

In my web.xml file I have:

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

contextConfigLocation classpath:shared-context.xml

<!--  Main general mapping, i.e. context for the UI & version queries -->
<servlet>
    <servlet-name>mainDispacherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
             <param-name>contextConfigLocation</param-name>
             <param-value>classpath:web-application-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>mainDispacherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<!-- Processes application requests for version 1 -->
<servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
              <param-name>contextConfigLocation</param-name>
              <param-value>classpath:version-api-contexts/application-context[v1.0].xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>/api/v1.0/*</url-pattern>
</servlet-mapping>

In the parent context, shared-context.xml, I have:

 <aop:aspectj-autoproxy/>

 <context:component-scan base-package="com.company.cse.support.audit"/>

the package com.company.cse.support.audit contains a class marked with @Component and @Aspect. This aspect logs a message to my audit log.

When I call a method on a bean defined in the child context version-api-contexts/application-context[v1.0].xml the bean is not proxied by spring AOP and the aspect doesn't get invoked. If I move the aspect definition line <context:component-scan base-package="com.company.cse.support.audit"/> to the child context XML, the aspect works fine.

I will eventually have many child contexts and I prefer not to have to put this line in each one of the child XML files. Is there a way to define common aspects once in the parent context and have them work in child contexts?

Doron Gold
  • 3,664
  • 4
  • 32
  • 44

2 Answers2

8

The creation of Spring AOP proxies takes place at the time of context loading through bean post-processors. As the child context gets loaded only after the parent context has already been loaded, a bean post-processor defined in the parent context cannot possibly affect beans in a child context.

If you want the beans in the child contexts to be proxied, you will have to ensure two things:

  1. The child context have access to the aspect beans (having them in the parent context is OK)
  2. The bean post processor that performs the proxying itself is included in the context

For #2 you will need <aop:aspectj-autoproxy/> in each child context definition. If you want to avoid repeating it, try to factor out parts common to all child contexts into a separate xml file that you can in turn import in each of them.

zagyi
  • 17,223
  • 4
  • 51
  • 48
0

In short, <aop:aspectj-autoproxy/> is a kind of bean post-processor, and the bean post processor is only able to affect aspect beans loaded in the same context or its parent context.

A bean post-processor cannot possibly affect beans in a child context (those beans are initialized after parent bean post-processor).

Peiming Hu
  • 517
  • 6
  • 8