|
|
|
@ -16,10 +16,14 @@
@@ -16,10 +16,14 @@
|
|
|
|
|
|
|
|
|
|
package org.springframework.context.annotation; |
|
|
|
|
|
|
|
|
|
import java.util.concurrent.Executors; |
|
|
|
|
import java.util.concurrent.TimeUnit; |
|
|
|
|
import java.util.concurrent.atomic.AtomicBoolean; |
|
|
|
|
import javax.annotation.Resource; |
|
|
|
|
|
|
|
|
|
import org.apache.commons.logging.Log; |
|
|
|
|
import org.apache.commons.logging.LogFactory; |
|
|
|
|
import org.awaitility.Awaitility; |
|
|
|
|
import org.junit.BeforeClass; |
|
|
|
|
import org.junit.Test; |
|
|
|
|
|
|
|
|
@ -32,19 +36,20 @@ import org.springframework.tests.Assume;
@@ -32,19 +36,20 @@ import org.springframework.tests.Assume;
|
|
|
|
|
import org.springframework.tests.TestGroup; |
|
|
|
|
import org.springframework.tests.sample.beans.ITestBean; |
|
|
|
|
import org.springframework.tests.sample.beans.TestBean; |
|
|
|
|
import org.springframework.util.StopWatch; |
|
|
|
|
|
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @author Juergen Hoeller |
|
|
|
|
* @author Chris Beams |
|
|
|
|
* @author Sam Brannen |
|
|
|
|
* @since 2.5 |
|
|
|
|
*/ |
|
|
|
|
public class AnnotationProcessorPerformanceTests { |
|
|
|
|
|
|
|
|
|
private static final Log factoryLog = LogFactory.getLog(DefaultListableBeanFactory.class); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@BeforeClass |
|
|
|
|
public static void commonAssumptions() { |
|
|
|
|
Assume.group(TestGroup.PERFORMANCE); |
|
|
|
@ -52,89 +57,79 @@ public class AnnotationProcessorPerformanceTests {
@@ -52,89 +57,79 @@ public class AnnotationProcessorPerformanceTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void testPrototypeCreationWithResourcePropertiesIsFastEnough() { |
|
|
|
|
GenericApplicationContext ctx = new GenericApplicationContext(); |
|
|
|
|
AnnotationConfigUtils.registerAnnotationConfigProcessors(ctx); |
|
|
|
|
ctx.refresh(); |
|
|
|
|
public void prototypeCreationWithResourcePropertiesIsFastEnough() { |
|
|
|
|
GenericApplicationContext ctx = createContext(); |
|
|
|
|
|
|
|
|
|
RootBeanDefinition rbd = new RootBeanDefinition(ResourceAnnotatedTestBean.class); |
|
|
|
|
rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE); |
|
|
|
|
ctx.registerBeanDefinition("test", rbd); |
|
|
|
|
ctx.registerBeanDefinition("spouse", new RootBeanDefinition(TestBean.class)); |
|
|
|
|
TestBean spouse = (TestBean) ctx.getBean("spouse"); |
|
|
|
|
StopWatch sw = new StopWatch(); |
|
|
|
|
sw.start("prototype"); |
|
|
|
|
for (int i = 0; i < 100000; i++) { |
|
|
|
|
TestBean tb = (TestBean) ctx.getBean("test"); |
|
|
|
|
assertThat(tb.getSpouse()).isSameAs(spouse); |
|
|
|
|
} |
|
|
|
|
sw.stop(); |
|
|
|
|
assertThat(sw.getTotalTimeMillis() < 4000).as("Prototype creation took too long: " + sw.getTotalTimeMillis()).isTrue(); |
|
|
|
|
|
|
|
|
|
assertFastEnough(ctx); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void testPrototypeCreationWithOverriddenResourcePropertiesIsFastEnough() { |
|
|
|
|
GenericApplicationContext ctx = new GenericApplicationContext(); |
|
|
|
|
AnnotationConfigUtils.registerAnnotationConfigProcessors(ctx); |
|
|
|
|
ctx.refresh(); |
|
|
|
|
public void prototypeCreationWithOverriddenResourcePropertiesIsFastEnough() { |
|
|
|
|
GenericApplicationContext ctx = createContext(); |
|
|
|
|
|
|
|
|
|
RootBeanDefinition rbd = new RootBeanDefinition(ResourceAnnotatedTestBean.class); |
|
|
|
|
rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE); |
|
|
|
|
rbd.getPropertyValues().add("spouse", new RuntimeBeanReference("spouse")); |
|
|
|
|
ctx.registerBeanDefinition("test", rbd); |
|
|
|
|
ctx.registerBeanDefinition("spouse", new RootBeanDefinition(TestBean.class)); |
|
|
|
|
TestBean spouse = (TestBean) ctx.getBean("spouse"); |
|
|
|
|
StopWatch sw = new StopWatch(); |
|
|
|
|
sw.start("prototype"); |
|
|
|
|
for (int i = 0; i < 100000; i++) { |
|
|
|
|
TestBean tb = (TestBean) ctx.getBean("test"); |
|
|
|
|
assertThat(tb.getSpouse()).isSameAs(spouse); |
|
|
|
|
} |
|
|
|
|
sw.stop(); |
|
|
|
|
assertThat(sw.getTotalTimeMillis() < 4000).as("Prototype creation took too long: " + sw.getTotalTimeMillis()).isTrue(); |
|
|
|
|
|
|
|
|
|
assertFastEnough(ctx); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void testPrototypeCreationWithAutowiredPropertiesIsFastEnough() { |
|
|
|
|
GenericApplicationContext ctx = new GenericApplicationContext(); |
|
|
|
|
AnnotationConfigUtils.registerAnnotationConfigProcessors(ctx); |
|
|
|
|
ctx.refresh(); |
|
|
|
|
public void prototypeCreationWithAutowiredPropertiesIsFastEnough() { |
|
|
|
|
GenericApplicationContext ctx = createContext(); |
|
|
|
|
|
|
|
|
|
RootBeanDefinition rbd = new RootBeanDefinition(AutowiredAnnotatedTestBean.class); |
|
|
|
|
rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE); |
|
|
|
|
ctx.registerBeanDefinition("test", rbd); |
|
|
|
|
ctx.registerBeanDefinition("spouse", new RootBeanDefinition(TestBean.class)); |
|
|
|
|
TestBean spouse = (TestBean) ctx.getBean("spouse"); |
|
|
|
|
StopWatch sw = new StopWatch(); |
|
|
|
|
sw.start("prototype"); |
|
|
|
|
for (int i = 0; i < 100000; i++) { |
|
|
|
|
TestBean tb = (TestBean) ctx.getBean("test"); |
|
|
|
|
assertThat(tb.getSpouse()).isSameAs(spouse); |
|
|
|
|
} |
|
|
|
|
sw.stop(); |
|
|
|
|
assertThat(sw.getTotalTimeMillis() < 4000).as("Prototype creation took too long: " + sw.getTotalTimeMillis()).isTrue(); |
|
|
|
|
|
|
|
|
|
assertFastEnough(ctx); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void testPrototypeCreationWithOverriddenAutowiredPropertiesIsFastEnough() { |
|
|
|
|
GenericApplicationContext ctx = new GenericApplicationContext(); |
|
|
|
|
AnnotationConfigUtils.registerAnnotationConfigProcessors(ctx); |
|
|
|
|
ctx.refresh(); |
|
|
|
|
public void prototypeCreationWithOverriddenAutowiredPropertiesIsFastEnough() { |
|
|
|
|
GenericApplicationContext ctx = createContext(); |
|
|
|
|
|
|
|
|
|
RootBeanDefinition rbd = new RootBeanDefinition(AutowiredAnnotatedTestBean.class); |
|
|
|
|
rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE); |
|
|
|
|
rbd.getPropertyValues().add("spouse", new RuntimeBeanReference("spouse")); |
|
|
|
|
ctx.registerBeanDefinition("test", rbd); |
|
|
|
|
ctx.registerBeanDefinition("spouse", new RootBeanDefinition(TestBean.class)); |
|
|
|
|
TestBean spouse = (TestBean) ctx.getBean("spouse"); |
|
|
|
|
StopWatch sw = new StopWatch(); |
|
|
|
|
sw.start("prototype"); |
|
|
|
|
for (int i = 0; i < 100000; i++) { |
|
|
|
|
TestBean tb = (TestBean) ctx.getBean("test"); |
|
|
|
|
assertThat(tb.getSpouse()).isSameAs(spouse); |
|
|
|
|
} |
|
|
|
|
sw.stop(); |
|
|
|
|
assertThat(sw.getTotalTimeMillis() < 6000).as("Prototype creation took too long: " + sw.getTotalTimeMillis()).isTrue(); |
|
|
|
|
|
|
|
|
|
assertFastEnough(ctx); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private GenericApplicationContext createContext() { |
|
|
|
|
GenericApplicationContext ctx = new GenericApplicationContext(); |
|
|
|
|
AnnotationConfigUtils.registerAnnotationConfigProcessors(ctx); |
|
|
|
|
ctx.refresh(); |
|
|
|
|
return ctx; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void assertFastEnough(GenericApplicationContext ctx) { |
|
|
|
|
AtomicBoolean done = new AtomicBoolean(); |
|
|
|
|
TestBean spouse = ctx.getBean("spouse", TestBean.class); |
|
|
|
|
Executors.newSingleThreadExecutor().submit(() -> { |
|
|
|
|
for (int i = 0; i < 100_000; i++) { |
|
|
|
|
TestBean tb = ctx.getBean("test", TestBean.class); |
|
|
|
|
assertThat(tb.getSpouse()).isSameAs(spouse); |
|
|
|
|
} |
|
|
|
|
done.set(true); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// "fast enough" is of course relative, but we're using 6 seconds with the hope
|
|
|
|
|
// that these tests typically pass on the CI server.
|
|
|
|
|
Awaitility.await() |
|
|
|
|
.atMost(6, TimeUnit.SECONDS) |
|
|
|
|
.pollInterval(100, TimeUnit.MILLISECONDS) |
|
|
|
|
.untilTrue(done); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|