Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>OK, I have solved the problem. Essentially, it is a Spring problem in conjunction with some custom extensions. If anyone comes across something similar, I will try to explain step by step what is happening.</p> <p>First of all, we have a custom <code>BeanDefintionParser</code> in our project. This class had the following definition:</p> <pre><code>private static class ControllerBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { protected Class&lt;?&gt; getBeanClass(Element element) { try { return Class.forName(element.getAttribute("class")); } catch (ClassNotFoundException e) { throw new RuntimeException("Class " + element.getAttribute("class") + "not found.", e); } } // code to parse XML omitted for brevity } </code></pre> <p>Now, the problem occurs after all bean definition have been read and <code>BeanDefinitionRegistryPostProcessor</code> begins to kick in. At this stage, a class called <code>ConfigurationClassPostProcessor</code> starts looking through all bean definitions, to search for bean classes annotated with <code>@Configuration</code> or that have methods with <code>@Bean</code>.</p> <p>In the process of reading annotations for a bean, it uses the <code>AnnotationMetadata</code> interface. For most regular beans, a subclass called <code>AnnotationMetadataVisitor</code> is used. However, when parsing the bean definitions, if you have overriden the <code>getBeanClass()</code> method to return a class instance, like we had, instead a <code>StandardAnnotationMetadata</code> instance is used. When <code>StandardAnnotationMetadata.hasAnnotatedMethods(..)</code> is invoked, it calls <code>Class.getDeclaredMethods()</code>, which in turn causes the class loader to load all classes used as parameters in that class. Classes loaded this way are not correctly unloaded, and thus never weaved, since this happens before the AspectJ transformer registered.</p> <p>Now, my problem was that I had a class like so:</p> <pre><code>public class Something { private Lang lang; public void setLang(Lang lang) { this.lang = lang; } } </code></pre> <p>Then, I had a bean of class <code>Something</code> that was parsed using our custom <code>ControllerBeanDefinitionParser</code>. This triggered the wrong annotation detection procedure, which triggered unexpected class loading, which meant that AspectJ never got a chance to weave <code>Lang</code>.</p> <p>The solution was to not override <code>getBeanClass(..)</code>, but instead override <code>getBeanClassName(..)</code>, which according to the documentation is preferable:</p> <pre><code>private static class ControllerBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { protected String getBeanClassName(Element element) { return element.getAttribute("class"); } // code to parse XML omitted for brevity } </code></pre> <p>Lesson of the day: Do not override <code>getBeanClass</code> unless you really mean it. Actually, don't try to write your own BeanDefinitionParser unless you know what you're doing.</p> <p>Fin.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload