[picocontainer-dev] RE: [picocontainer-scm] [4525] java/2.x/trunk/pico/container/src/test/org/picocontainer/defaults: constructor injection speedup : remembers (optionally) the constructor to use
"Michael Rimov" <[email protected]>
| Newsgroups | gmane.comp.java.picocontainer.devel |
|---|---|
| Organization | Centerline Computers, Inc |
| Message-ID | <00b801c8c205$638c1910$2aa44b30$@com> |
Silly question: is there a reason why you wouldn’t want to remember the constructor to use? I can only think of memory resources, but if we did SoftReferences, we probably could strike a happy medium and save all the if/else clauses.
-Mike
From: paul-yCVjj/[email protected] [mailto:paul-yCVjj/[email protected]]
Sent: Thursday, May 29, 2008 7:39 PM
To: scm-qxt/[email protected]
Subject: [picocontainer-scm] [4525] java/2.x/trunk/pico/container/src/test/org/picocontainer/defaults: constructor injection speedup : remembers (optionally) the constructor to use
Revision
4525 <http://fisheye.codehaus.org/changelog/picocontainer/?cs=4525>
Author
paul
Date
2008-05-29 21:39:06 -0500 (Thu, 29 May 2008)
Log Message
constructor injection speedup : remembers (optionally) the constructor to use
Modified Paths
* java/2.x/trunk/pico/container/src/java/org/picocontainer/injectors/ConstructorInjector.java <>
* java/2.x/trunk/pico/container/src/test/org/picocontainer/defaults/PicoExceptionsTestCase.java <>
* java/2.x/trunk/pico/container/src/test/org/picocontainer/injectors/AdaptingInjectionTestCase.java <>
* java/2.x/trunk/pico/container/src/test/org/picocontainer/injectors/ConstructorInjectorTestCase.java <>
Diff
Modified: java/2.x/trunk/pico/container/src/java/org/picocontainer/injectors/ConstructorInjector.java (4524 => 4525)
--- java/2.x/trunk/pico/container/src/java/org/picocontainer/injectors/ConstructorInjector.java 2008-05-29 18:25:08 UTC (rev 4524)
+++ java/2.x/trunk/pico/container/src/java/org/picocontainer/injectors/ConstructorInjector.java 2008-05-30 02:39:06 UTC (rev 4525)
@@ -47,12 +47,13 @@
/**
* Serialization UUID.
*/
- private static final long serialVersionUID = 3663020107106785481L;
+ private static final long serialVersionUID = 3663020107106785481L;
private transient List<Constructor<T>> sortedMatchingConstructors;
private transient ThreadLocalCyclicDependencyGuard<T> instantiationGuard;
-
-
+ private boolean rememberChosenConstructor = true;
+ private transient Constructor<T> chosenConstructor;
+
/**
* Constructor injector that uses no monitor and no lifecycle adapter. This is a more
* convenient constructor for use when instantiating a constructor injector directly.
@@ -82,6 +83,26 @@
super(componentKey, componentImplementation, parameters, monitor, lifecycleStrategy, useNames);
}
+ /**
+ * Creates a ConstructorInjector
+ *
+ * @param componentKey the search key for this implementation
+ * @param componentImplementation the concrete implementation
+ * @param parameters the parameters to use for the initialization
+ * @param monitor the component monitor used by this addAdapter
+ * @param lifecycleStrategy the component lifecycle strategy used by this addAdapter
+ * @param useNames use argument names when looking up dependencies
+ * @param rememberChosenCtor remember the chosen constructor (to speed up second/subsequent calls)
+ * @throws org.picocontainer.injectors.AbstractInjector.NotConcreteRegistrationException
+ * if the implementation is not a concrete class.
+ * @throws NullPointerException if one of the parameters is <code>null</code>
+ */
+ public ConstructorInjector(final Object componentKey, final Class componentImplementation, Parameter[] parameters, ComponentMonitor monitor,
+ LifecycleStrategy lifecycleStrategy, boolean useNames, boolean rememberChosenCtor) throws NotConcreteRegistrationException {
+ super(componentKey, componentImplementation, parameters, monitor, lifecycleStrategy, useNames);
+ this.rememberChosenConstructor = rememberChosenCtor;
+ }
+
protected Constructor<T> getGreediestSatisfiableConstructor(PicoContainer container) throws PicoCompositionException {
final Set<Constructor> conflicts = new HashSet<Constructor>();
final Set<List<Class>> unsatisfiableDependencyTypes = new HashSet<List<Class>>();
@@ -145,34 +166,42 @@
return greediestConstructor;
}
-
public T getComponentInstance(final PicoContainer container, Type into) throws PicoCompositionException {
if (instantiationGuard == null) {
instantiationGuard = new ThreadLocalCyclicDependencyGuard<T>() {
public T run() {
- Constructor<T> constructor;
+ Constructor<T> ctor = null;
try {
- constructor = getGreediestSatisfiableConstructor(guardedContainer);
+ if (chosenConstructor == null) {
+ ctor = getGreediestSatisfiableConstructor(guardedContainer);
+ }
+ if (rememberChosenConstructor) {
+ if (chosenConstructor == null) {
+ chosenConstructor = ctor;
+ } else {
+ ctor = chosenConstructor;
+ }
+ }
} catch (AmbiguousComponentResolutionException e) {
e.setComponent(getComponentImplementation());
throw e;
}
ComponentMonitor componentMonitor = currentMonitor();
try {
- Object[] parameters = getMemberArguments(guardedContainer, constructor);
- constructor = componentMonitor.instantiating(container, ConstructorInjector.this, constructor);
- if(constructor == null) {
+ Object[] parameters = getMemberArguments(guardedContainer, ctor);
+ ctor = componentMonitor.instantiating(container, ConstructorInjector.this, ctor);
+ if(ctor == null) {
throw new NullPointerException("Component Monitor " + componentMonitor
- + " returned a null constructor from method 'instantiating' after passing in " + constructor);
+ + " returned a null constructor from method 'instantiating' after passing in " + ctor);
}
long startTime = System.currentTimeMillis();
- T inst = instantiate(constructor, parameters);
+ T inst = instantiate(ctor, parameters);
componentMonitor.instantiated(container,
ConstructorInjector.this,
- constructor, inst, parameters, System.currentTimeMillis() - startTime);
+ ctor, inst, parameters, System.currentTimeMillis() - startTime);
return inst;
} catch (InvocationTargetException e) {
- componentMonitor.instantiationFailed(container, ConstructorInjector.this, constructor, e);
+ componentMonitor.instantiationFailed(container, ConstructorInjector.this, ctor, e);
if (e.getTargetException() instanceof RuntimeException) {
throw (RuntimeException) e.getTargetException();
} else if (e.getTargetException() instanceof Error) {
@@ -180,9 +209,9 @@
}
throw new PicoCompositionException(e.getTargetException());
} catch (InstantiationException e) {
- return caughtInstantiationException(componentMonitor, constructor, e, container);
+ return caughtInstantiationException(componentMonitor, ctor, e, container);
} catch (IllegalAccessException e) {
- return caughtIllegalAccessException(componentMonitor, constructor, e, container);
+ return caughtIllegalAccessException(componentMonitor, ctor, e, container);
}
}
Modified: java/2.x/trunk/pico/container/src/test/org/picocontainer/defaults/PicoExceptionsTestCase.java (4524 => 4525)
--- java/2.x/trunk/pico/container/src/test/org/picocontainer/defaults/PicoExceptionsTestCase.java 2008-05-29 18:25:08 UTC (rev 4524)
+++ java/2.x/trunk/pico/container/src/test/org/picocontainer/defaults/PicoExceptionsTestCase.java 2008-05-30 02:39:06 UTC (rev 4525)
@@ -43,7 +43,7 @@
@SuppressWarnings({ "unchecked" })
final void executeTestOfStandardException(final Class clazz) {
final ComponentAdapter componentAdapter = new ConstructorInjector(clazz, clazz, null, new AbstractComponentMonitor(),
- new NullLifecycleStrategy(), false);
+ new NullLifecycleStrategy(), false, false);
DefaultPicoContainer pico = new DefaultPicoContainer();
pico.addComponent(MESSAGE);
try {
Modified: java/2.x/trunk/pico/container/src/test/org/picocontainer/injectors/AdaptingInjectionTestCase.java (4524 => 4525)
--- java/2.x/trunk/pico/container/src/test/org/picocontainer/injectors/AdaptingInjectionTestCase.java 2008-05-29 18:25:08 UTC (rev 4524)
+++ java/2.x/trunk/pico/container/src/test/org/picocontainer/injectors/AdaptingInjectionTestCase.java 2008-05-30 02:39:06 UTC (rev 4525)
@@ -119,6 +119,7 @@
String foo = xs.toXML(ca).replace("\"", "");
assertEquals("<Constructor-Injection>\n" +
+ " <rememberChosenConstructor>true</rememberChosenConstructor>\n" +
" <lifecycleStrategy class=RLS/>\n" +
" <useNames>false</useNames>\n" +
" <componentKey class=java-class>java.util.Map</componentKey>\n" +
Modified: java/2.x/trunk/pico/container/src/test/org/picocontainer/injectors/ConstructorInjectorTestCase.java (4524 => 4525)
--- java/2.x/trunk/pico/container/src/test/org/picocontainer/injectors/ConstructorInjectorTestCase.java 2008-05-29 18:25:08 UTC (rev 4524)
+++ java/2.x/trunk/pico/container/src/test/org/picocontainer/injectors/ConstructorInjectorTestCase.java 2008-05-30 02:39:06 UTC (rev 4525)
@@ -373,4 +373,53 @@
cica.dispose(touchable);
assertEquals("<start<stop<dispose", strategy.recording());
}
+
+ public static class One {
+ public One(Two two) {
+ two.inc();
+ }
+ }
+ public static class Two {
+ private int inc;
+ public void inc() {
+ inc++;
+ }
+
+ public long howMany() {
+ return inc;
+ }
+ }
+
+ @Test public void testSpeedOfRememberedConstructor() {
+ long with, without;
+ timeIt(); // discard
+ timeIt(); // discard
+ timeIt(); // discard
+ rememberChosenCtor = false;
+ without = timeIt();
+ rememberChosenCtor = true;
+ with = timeIt();
+ System.out.println("-->testSpeedOfRememberedConstructor(): durations:" + with + " " + without);
+ assertTrue("with should be < without but were " + with + " and " + without, with < without);
+ }
+
+ boolean rememberChosenCtor;
+ private long timeIt() {
+ int iterations = 20000;
+ long with;
+ DefaultPicoContainer dpc = new DefaultPicoContainer();
+ Two two = new Two();
+ dpc.addComponent(two);
+ dpc.addAdapter(new ConstructorInjector(One.class, One.class, null,
+ new NullComponentMonitor(),
+ new NullLifecycleStrategy(), false, rememberChosenCtor));
+ long start = System.currentTimeMillis();
+ for (int x = 0; x < iterations; x++) {
+ One one = dpc.getComponent(One.class);
+ }
+ long end = System.currentTimeMillis();
+ assertEquals(iterations, two.howMany());
+ return end-start;
+ }
+
}
_____
To unsubscribe from this list please visit:
http://xircles.codehaus.org/manage_email