@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..
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 scopeprototype
, 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.