@Component
@Scope(value = BeanDefinition.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ShouldBePrototype {

}

Class above is not prototype. I wrote test to prove that

@RunWith(SpringRunner.class)
@SpringBootApplication
public class NotPrototypeApplicationTests {
    @Autowired
    ObjectFactory <ShouldBePrototype> shouldBePrototypeFactory;

    @Test
    public void notOk() {
        assert (shouldBePrototypeFactory.getObject() != shouldBePrototypeFactory.getObject());
    }

}

Test is fail.

Full project to reproduce https://github.com/MEJIOMAH17/funnyPrototype

Comment From: bhargavjanjam

@MEJIOMAH17 .. i tried running the test class on my local.. it is working fine.. may be there is some problem with the IDE.. please try running the class from the command line.. Screen Shot 2019-10-13 at 10 29 35 PM

Comment From: MEJIOMAH17

@bhargavjanjam from command line I have same result. command is mvn test surefire-reports.zip

Apache Maven 3.6.0 Maven home: /usr/share/maven Java version: 1.8.0_222, vendor: Private Build, runtime: /usr/lib/jvm/java-8-openjdk-amd64/jre Default locale: en_US, platform encoding: UTF-8 OS name: "linux", version: "5.0.0-32-generic", arch: "amd64", family: "unix"

Comment From: sbrannen

@MEJIOMAH17, what happens if you modify your test as follows?

@Test
public void notOk() {
    ShouldBePrototype proxy1 = shouldBePrototypeFactory.getObject();
    ShouldBePrototype proxy2 = shouldBePrototypeFactory.getObject();

    ShouldBePrototype target1 = AopTestUtils.getUltimateTargetObject(proxy1);
    ShouldBePrototype target2 = AopTestUtils.getUltimateTargetObject(proxy2);

    assert (target1 != target2);
}

Comment From: sbrannen

@MEJIOMAH17 .. i tried running the test class on my local.. it is working fine.. may be there is some problem with the IDE..

@bhargavjanjam, are you sure that you have the -ea VM argument set in the Eclipse Run Configuration for that test?

Comment From: sbrannen

@MEJIOMAH17, out of curiosity, why do you want to use a scoped proxy for your prototype bean?

Comment From: MEJIOMAH17

@sbrannen I hunting for bug in my code, and randomly found that bug. In my case there are no sense use scoped proxy.

Comment From: MEJIOMAH17

@sbrannen

  /**
     * https://github.com/spring-projects/spring-framework/issues/23725#issuecomment-546374463
     */
    @Test
    public void sbrannenRecommendation() {
        ShouldBePrototype proxy1 = shouldBePrototypeFactory.getObject();
        ShouldBePrototype proxy2 = shouldBePrototypeFactory.getObject();

        ShouldBePrototype target1 = AopTestUtils.getUltimateTargetObject(proxy1);
        ShouldBePrototype target2 = AopTestUtils.getUltimateTargetObject(proxy2);

        assert (target1 != target2);

        ShouldBePrototype shouldBeEqualTarget1 = AopTestUtils.getUltimateTargetObject(proxy1);
        assert (shouldBeEqualTarget1 == proxy1);

    }

Second assert failed.

P.S. Test above added to https://github.com/MEJIOMAH17/funnyPrototype

Comment From: sbrannen

Second assert failed.

That's to be expected: the proxy and the target it wraps are always two different objects in memory.

Comment From: MEJIOMAH17

@sbrannen My bad. Bug in my assert. Correct assert also failed.

  @Test
    public void sbrannenRecommendation() {
        ShouldBePrototype proxy1 = shouldBePrototypeFactory.getObject();
        ShouldBePrototype proxy2 = shouldBePrototypeFactory.getObject();

        ShouldBePrototype target1 = AopTestUtils.getUltimateTargetObject(proxy1);
        ShouldBePrototype target2 = AopTestUtils.getUltimateTargetObject(proxy2);

        assert (target1 != target2);

        ShouldBePrototype shouldBeEqualTarget1 = AopTestUtils.getUltimateTargetObject(proxy1);

        assert (shouldBeEqualTarget1 == target1);

    }

P.S. Test updated in https://github.com/MEJIOMAH17/funnyPrototype

Comment From: MEJIOMAH17

@sbrannen is it bug, or it's feature?

Comment From: sbrannen

Hi @MEJIOMAH17,

First and foremost, apologies for the belated reply. This one slipped through the cracks.

is it bug, or it's feature?

Well, it "works as designed", and this behavior is documented in the reference manual:

When declaring <aop:scoped-proxy/> against a bean of scope prototype, every method call on the shared proxy leads to the creation of a new target instance to which the call is then being forwarded.

That refers to XML configuration, but the same applies to @Scope(scopeName = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS).

So, even though it's technically a "feature", I'd say it's a "bug" in your code.

For what it's worth, the reference documentation used to provide the following tip.

You do not need to use the <aop:scoped-proxy/> in conjunction with beans that are scoped as singletons or prototypes.

And I consider that solid advice.

In light of that, I am closing this issue.