<p dir="auto"><strong><a href="https://jira.spring.io/secure/ViewProfile.jspa?name=sgybas" rel="nofollow">Stefan Gybas</a></strong> opened <strong><a href="https://jira.spring.io/browse/SPR-8434?redirect=false" rel="nofollow">SPR-8434</a></strong> and commented</p>
<p dir="auto">We are migrating a project from Java 5 to Java 6 and noticed that one integration test was failing because a dependency was not injected any longer.</p>
<p dir="auto">The problem can be reproduced with a simple scenario: We have a package-visible base class for some services with an autowired dependency and a public getter and setter:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="abstract class AbstractService {

    private Dependency dependency;

    public Dependency getDependency() {
        return dependency;
    }

    @Autowired
    public void setDependency(Dependency dependency) {
        this.dependency = dependency;
    }
}"><pre class="notranslate"><code class="notranslate">abstract class AbstractService {

    private Dependency dependency;

    public Dependency getDependency() {
        return dependency;
    }

    @Autowired
    public void setDependency(Dependency dependency) {
        this.dependency = dependency;
    }
}
</code></pre></div>
<p dir="auto">Then he have a public sub class that gets component-scanned:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="@Component
public class Service extends AbstractService {
}"><pre class="notranslate"><code class="notranslate">@Component
public class Service extends AbstractService {
}
</code></pre></div>
<p dir="auto">Our test basically looks like this:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { &quot;/applicationContext.xml&quot; })
public class DependencyInjectionTest {

    @Autowired
    private Service underTest;

    @Test
    public void testDependencyInjected() {
        // this test passes when Service.java was compiled with Java 5
        // but fails when compiled with Java 6
        assertNotNull(underTest.getDependency());
    }
}"><pre class="notranslate"><code class="notranslate">@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/applicationContext.xml" })
public class DependencyInjectionTest {

    @Autowired
    private Service underTest;

    @Test
    public void testDependencyInjected() {
        // this test passes when Service.java was compiled with Java 5
        // but fails when compiled with Java 6
        assertNotNull(underTest.getDependency());
    }
}
</code></pre></div>
<p dir="auto">with a very simple application context that just enables annotation-config and does a package scan (see the attachment for a complete Maven/Eclipse project).</p>
<p dir="auto">When we compile the project with Java 5 the test passes when run with Java 5 or Java 6. But when we compile the project with Java 6 ("-source 1.5 -target 1.5") the test fails both under Java 5 and Java 6.</p>
<p dir="auto">After investigating the byte code in Service.class we noticed that two bridge methods are generated by the Java 6 compiler. These methods are not generated by the Java 5 compiler:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="public com.example.Dependency com.example.Service.getDependency() (bridge: true)
public void com.example.Service.setDependency(com.example.Dependency) (bridge: true)"><pre class="notranslate"><code class="notranslate">public com.example.Dependency com.example.Service.getDependency() (bridge: true)
public void com.example.Service.setDependency(com.example.Dependency) (bridge: true)
</code></pre></div>
<p dir="auto">AutowiredAnnotationBeanPostProcessor.buildAutowiringMetadata(Class clazz) uses ClassUtils.getMostSpecificMethod() in line 346 (current SVN) to determine if the method is defined in the class that is investigated (AbstractService in the example). The most specific method is the bridge method in Service.class when compiled with Java 6 but this method does not have the <code class="notranslate">@Autowired</code> annotation so the setter is never called.</p>
<p dir="auto">A fix would be to replace ClassUtils.getMostSpecificMethod() with AopUtils.getMostSpecificMethod() to get the same results on Java 5 and Java 6. But this would cause a circular dependency between spring-aop and spring-beans and is probably not a high-performance solution.</p>
<p dir="auto">We will change the visibility of AbstractService to public in our project to work around the problem. But I suggest to change Spring to deliver the same results on Java 5 and Java 6.</p>
<hr>
<p dir="auto"><strong>Affects:</strong> 3.0.5, 3.1 M2</p>
<p dir="auto"><strong>Attachments:</strong></p>
<ul dir="auto">
<li><a href="https://jira.spring.io/secure/attachment/18326/DependencyTest.zip" rel="nofollow">DependencyTest.zip</a> (<em>6.13 kB</em>)</li>
</ul>
<p dir="auto"><strong>Issue Links:</strong></p>
<ul dir="auto">
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398109765" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/12555" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/12555/hovercard" href="https://github.com/spring-projects/spring-framework/issues/12555">#12555</a> Annotation based injection into non public base classes does not work (<em><strong>"duplicates"</strong></em>)</li>
</ul>
<p dir="auto"><strong><a href="https://jira.spring.io/secure/ViewProfile.jspa?name=cbeams" rel="nofollow">Chris Beams</a></strong> opened <strong><a href="https://jira.spring.io/browse/SPR-8141?redirect=false" rel="nofollow">SPR-8141</a></strong> and commented</p>
<hr>
<p dir="auto">This issue is a sub-task of <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398110688" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/12694" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/12694/hovercard" href="https://github.com/spring-projects/spring-framework/issues/12694">#12694</a></p>
<p dir="auto"><strong>Issue Links:</strong></p>
<ul dir="auto">
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398109677" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/12544" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/12544/hovercard" href="https://github.com/spring-projects/spring-framework/issues/12544">#12544</a> Introduce <code class="notranslate">@EnableSpringConfigured</code> (<em><strong>"duplicates"</strong></em>)</li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398111214" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/12790" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/12790/hovercard" href="https://github.com/spring-projects/spring-framework/issues/12790">#12790</a> SpringConfiguredBeanDefinitionParser (aop:spring-configured) (<em><strong>"is duplicated by"</strong></em>)</li>
</ul>