166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee/** 266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * Copyright (C) 2006 Google Inc. 366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * 466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * Licensed under the Apache License, Version 2.0 (the "License"); 566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * you may not use this file except in compliance with the License. 666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * You may obtain a copy of the License at 766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * 866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * http://www.apache.org/licenses/LICENSE-2.0 966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * 1066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * Unless required by applicable law or agreed to in writing, software 1166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * distributed under the License is distributed on an "AS IS" BASIS, 1266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * See the License for the specific language governing permissions and 1466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * limitations under the License. 1566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee */ 1666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 1766b415a2066cac9f36ed58070777de388f63a3a4crazybobleepackage com.google.inject; 1866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 19c0c12ea61414709600577bb547e1e77b4a405691kevinbimport static java.lang.annotation.RetentionPolicy.RUNTIME; 206a565c7216be86b23ae7390febd6c1f061a3981fkevinbimport static junit.framework.Assert.assertEquals; 216a565c7216be86b23ae7390febd6c1f061a3981fkevinbimport static junit.framework.Assert.assertSame; 22b7a02b02d81c830d148355c90bc309bcd66fb592sberlin 2366b415a2066cac9f36ed58070777de388f63a3a4crazybobleeimport org.springframework.beans.MutablePropertyValues; 2466b415a2066cac9f36ed58070777de388f63a3a4crazybobleeimport org.springframework.beans.factory.config.ConstructorArgumentValues; 2566b415a2066cac9f36ed58070777de388f63a3a4crazybobleeimport org.springframework.beans.factory.config.RuntimeBeanReference; 2666b415a2066cac9f36ed58070777de388f63a3a4crazybobleeimport org.springframework.beans.factory.support.DefaultListableBeanFactory; 2766b415a2066cac9f36ed58070777de388f63a3a4crazybobleeimport org.springframework.beans.factory.support.RootBeanDefinition; 2866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 29b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport java.lang.annotation.Retention; 30b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport java.text.DecimalFormat; 31b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport java.util.concurrent.Callable; 32b7a02b02d81c830d148355c90bc309bcd66fb592sberlin 3366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee/** 34e9f0fa57c4b41b803faa42273bd8697f531a5fb8crazyboblee * A semi-useless microbenchmark. Spring and Guice constuct the same object 35e9f0fa57c4b41b803faa42273bd8697f531a5fb8crazyboblee * graph a bunch of times, and we see who can construct the most per second. 36e9f0fa57c4b41b803faa42273bd8697f531a5fb8crazyboblee * As of this writing Guice is more than 50X faster. Also useful for comparing 37e9f0fa57c4b41b803faa42273bd8697f531a5fb8crazyboblee * pure Java configuration options. 3866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * 3966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee * @author crazybob@google.com (Bob Lee) 4066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee */ 41041e93387a67a7d15330592077b08577b2961a2ecrazybobleepublic class PerformanceComparison { 4266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 43e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee public static void main(String[] args) throws Exception { 44e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee // Once warm up. Takes lazy loading out of the equation and ensures we 45e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee // created the graphs properly. 46e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee validate(springFactory); 47e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee validate(juiceFactory); 48e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee validate(byHandFactory); 49e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee 50e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee for (int i2 = 0; i2 < 10; i2++) { 51e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee iterate(springFactory, "Spring: "); 52e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee iterate(juiceFactory, "Guice: "); 53e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee iterate(byHandFactory, "By Hand: "); 54e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee 55e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee System.err.println(); 56e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee } 573ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee 583ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee System.err.println("Concurrent:"); 593ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee 603ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee for (int i2 = 0; i2 < 10; i2++) { 613ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee concurrentlyIterate(springFactory, "Spring: "); 623ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee concurrentlyIterate(juiceFactory, "Guice: "); 633ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee concurrentlyIterate(byHandFactory, "By Hand: "); 643ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee 653ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee System.err.println(); 663ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee } 67e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee } 68e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee 6966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee static final Callable<Foo> springFactory = new Callable<Foo>() { 7066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 7166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee final DefaultListableBeanFactory beanFactory; 7266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 7366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee { 7466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee beanFactory = new DefaultListableBeanFactory(); 7566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 7666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee RootBeanDefinition tee = new RootBeanDefinition(TeeImpl.class, true); 7766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee tee.setLazyInit(true); 7866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee ConstructorArgumentValues teeValues = new ConstructorArgumentValues(); 7966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee teeValues.addGenericArgumentValue("test"); 8066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee tee.setConstructorArgumentValues(teeValues); 8166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 8266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee RootBeanDefinition bar = new RootBeanDefinition(BarImpl.class, false); 8366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee ConstructorArgumentValues barValues = new ConstructorArgumentValues(); 8466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee barValues.addGenericArgumentValue(new RuntimeBeanReference("tee")); 8566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee barValues.addGenericArgumentValue(5); 8666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee bar.setConstructorArgumentValues(barValues); 8766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 8866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee RootBeanDefinition foo = new RootBeanDefinition(Foo.class, false); 8966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee MutablePropertyValues fooValues = new MutablePropertyValues(); 9066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee fooValues.addPropertyValue("i", 5); 9166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee fooValues.addPropertyValue("bar", new RuntimeBeanReference("bar")); 9266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee fooValues.addPropertyValue("copy", new RuntimeBeanReference("bar")); 9366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee fooValues.addPropertyValue("s", "test"); 9466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee foo.setPropertyValues(fooValues); 9566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 9666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee beanFactory.registerBeanDefinition("foo", foo); 9766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee beanFactory.registerBeanDefinition("bar", bar); 9866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee beanFactory.registerBeanDefinition("tee", tee); 9966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee } 10066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 10166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee public Foo call() throws Exception { 10266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee return (Foo) beanFactory.getBean("foo"); 10366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee } 10466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee }; 10566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 10666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee static final Callable<Foo> juiceFactory = new Callable<Foo>() { 107bd9544e08ba5d41995024e7e301faf465457e593crazyboblee final Provider<Foo> fooProvider; 1087c5b2c4e5e3607c63c2785c8bc025706a158db80crazyboblee { 109a2915a9855e2d110c708425ec44854587e419790kevinb Injector injector; 1109bb62020927911172430dc3d94ee61796d519236crazyboblee try { 111a2915a9855e2d110c708425ec44854587e419790kevinb injector = Guice.createInjector(new AbstractModule() { 112db85d9c090a13457c47b91d018aad3aa8cecbb7ekevinb protected void configure() { 113db85d9c090a13457c47b91d018aad3aa8cecbb7ekevinb bind(Tee.class).to(TeeImpl.class); 114db85d9c090a13457c47b91d018aad3aa8cecbb7ekevinb bind(Bar.class).to(BarImpl.class); 115db85d9c090a13457c47b91d018aad3aa8cecbb7ekevinb bind(Foo.class); 1169e139521222140cba64ed77935d980d76644e4b0crazyboblee bindConstant().annotatedWith(I.class).to(5); 1179e139521222140cba64ed77935d980d76644e4b0crazyboblee bindConstant().annotatedWith(S.class).to("test"); 118db85d9c090a13457c47b91d018aad3aa8cecbb7ekevinb } 119db85d9c090a13457c47b91d018aad3aa8cecbb7ekevinb }); 1205746d5d7f2a97a9720ee33a7c7f9cc8e60e5cc71crazyboblee } catch (CreationException e) { 1219bb62020927911172430dc3d94ee61796d519236crazyboblee throw new RuntimeException(e); 1229bb62020927911172430dc3d94ee61796d519236crazyboblee } 123a2915a9855e2d110c708425ec44854587e419790kevinb fooProvider = injector.getProvider(Foo.class); 1247c5b2c4e5e3607c63c2785c8bc025706a158db80crazyboblee } 12566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 12666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee public Foo call() throws Exception { 127bd9544e08ba5d41995024e7e301faf465457e593crazyboblee return fooProvider.get(); 12866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee } 12966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee }; 13066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 1319e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee static final Callable<Foo> byHandFactory = new Callable<Foo>() { 1329e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee final Tee tee = new TeeImpl("test"); 1339e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee public Foo call() throws Exception { 1349e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee Foo foo = new Foo(); 1359e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee foo.setI(5); 1369e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee foo.setS("test"); 1379e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee Bar bar = new BarImpl(tee, 5); 1389e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee Bar copy = new BarImpl(tee, 5); 1399e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee foo.setBar(bar); 1409e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee foo.setCopy(copy); 1419e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee return foo; 1429e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee } 1439e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee }; 1449e5fe5d549368dc52aa1d79f1f70ac0146a51542crazyboblee 14566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee static void validate(Callable<Foo> t) throws Exception { 14666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee Foo foo = t.call(); 14766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee assertEquals(5, foo.i); 14866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee assertEquals("test", foo.s); 14966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee assertSame(foo.bar.getTee(), foo.copy.getTee()); 15066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee assertEquals(5, foo.bar.getI()); 15166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee assertEquals("test", foo.bar.getTee().getS()); 15266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee } 15366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 1546a565c7216be86b23ae7390febd6c1f061a3981fkevinb static final DecimalFormat format = new DecimalFormat(); 15566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 1563ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee static void iterate(Callable<Foo> callable, String label) { 157041e93387a67a7d15330592077b08577b2961a2ecrazyboblee int count = 100000; 1583ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee 159041e93387a67a7d15330592077b08577b2961a2ecrazyboblee long time = System.currentTimeMillis(); 1603ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee 161041e93387a67a7d15330592077b08577b2961a2ecrazyboblee for (int i = 0; i < count; i++) { 1623ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee try { 1633ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee callable.call(); 1643ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee } 1653ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee catch (Exception e) { 1663ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee throw new RuntimeException(e); 1673ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee } 1683ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee } 1693ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee 1703ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee time = System.currentTimeMillis() - time; 1713ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee 1723ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee System.err.println(label 1733ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee + format.format(count * 1000 / time) + " creations/s"); 1743ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee } 1753ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee 1763ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee static void concurrentlyIterate(final Callable<Foo> callable, String label) { 1773ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee int threadCount = 10; 1783ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee final int count = 10000; 1793ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee 1803ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee Thread[] threads = new Thread[threadCount]; 1813ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee 1823ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee for (int i = 0; i < threadCount; i++) { 1833ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee threads[i] = new Thread() { 1843ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee public void run() { 1853ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee for (int i = 0; i < count; i++) { 1863ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee try { 1873ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee validate(callable); 1883ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee } 1893ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee catch (Exception e) { 1903ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee throw new RuntimeException(e); 1913ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee } 1923ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee } 1933ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee } 1943ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee }; 1953ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee } 1963ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee 1973ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee 1983ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee long time = System.currentTimeMillis(); 1993ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee 2003ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee for (int i = 0; i < threadCount; i++) { 2013ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee threads[i].start(); 202041e93387a67a7d15330592077b08577b2961a2ecrazyboblee } 2033ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee 2043ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee for (int i = 0; i < threadCount; i++) { 2053ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee try { 2063ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee threads[i].join(); 2073ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee } 2083ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee catch (InterruptedException e) { 2093ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee throw new RuntimeException(e); 2103ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee } 2113ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee } 2123ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee 213041e93387a67a7d15330592077b08577b2961a2ecrazyboblee time = System.currentTimeMillis() - time; 2143ea63ff1115a2a8bf1999fd763f699930efe701acrazyboblee 215e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee System.err.println(label 216e3adfd619abae820b90951f383ec7a271a62c0b0crazyboblee + format.format(count * 1000 / time) + " creations/s"); 217041e93387a67a7d15330592077b08577b2961a2ecrazyboblee } 218041e93387a67a7d15330592077b08577b2961a2ecrazyboblee 21966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee public static class Foo { 22066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 22166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee Bar bar; 22266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee Bar copy; 22366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee String s; 22466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee int i; 22566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 2264602a6fe08692b38cf36aa3cdb5c4e340e6929d7crazyboblee @Inject 2271c4d3e37ba5aa517819f56e8544c4269b8ccadc3crazyboblee public void setI(@I int i) { 22866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee this.i = i; 22966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee } 23066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 23166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee @Inject 23266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee public void setBar(Bar bar) { 23366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee this.bar = bar; 23466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee } 23566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 23666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee @Inject 23766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee public void setCopy(Bar copy) { 23866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee this.copy = copy; 23966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee } 24066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 2414602a6fe08692b38cf36aa3cdb5c4e340e6929d7crazyboblee @Inject 2421c4d3e37ba5aa517819f56e8544c4269b8ccadc3crazyboblee public void setS(@S String s) { 24366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee this.s = s; 24466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee } 24566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee } 24666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 24766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee interface Bar { 24866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 24966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee Tee getTee(); 25066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee int getI(); 25166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee } 25266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 25366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee public static class BarImpl implements Bar { 25466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 25566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee final int i; 25666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee final Tee tee; 25766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 25866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee @Inject 2591c4d3e37ba5aa517819f56e8544c4269b8ccadc3crazyboblee public BarImpl(Tee tee, @I int i) { 26066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee this.tee = tee; 26166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee this.i = i; 26266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee } 26366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 26466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee public Tee getTee() { 26566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee return tee; 26666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee } 26766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 26866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee public int getI() { 26966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee return i; 27066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee } 27166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee } 27266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 27366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee interface Tee { 27466b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 27566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee String getS(); 27666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee } 27766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 278a2915a9855e2d110c708425ec44854587e419790kevinb @Singleton 27966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee public static class TeeImpl implements Tee { 28066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 28166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee final String s; 28266b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 28366b415a2066cac9f36ed58070777de388f63a3a4crazyboblee @Inject 2841c4d3e37ba5aa517819f56e8544c4269b8ccadc3crazyboblee public TeeImpl(@S String s) { 28566b415a2066cac9f36ed58070777de388f63a3a4crazyboblee this.s = s; 28666b415a2066cac9f36ed58070777de388f63a3a4crazyboblee } 28766b415a2066cac9f36ed58070777de388f63a3a4crazyboblee 28866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee public String getS() { 28966b415a2066cac9f36ed58070777de388f63a3a4crazyboblee return s; 29066b415a2066cac9f36ed58070777de388f63a3a4crazyboblee } 29166b415a2066cac9f36ed58070777de388f63a3a4crazyboblee } 2921c4d3e37ba5aa517819f56e8544c4269b8ccadc3crazyboblee 2931c4d3e37ba5aa517819f56e8544c4269b8ccadc3crazyboblee @Retention(RUNTIME) 294c0c12ea61414709600577bb547e1e77b4a405691kevinb @BindingAnnotation @interface I {} 2951c4d3e37ba5aa517819f56e8544c4269b8ccadc3crazyboblee 2961c4d3e37ba5aa517819f56e8544c4269b8ccadc3crazyboblee @Retention(RUNTIME) 297c0c12ea61414709600577bb547e1e77b4a405691kevinb @BindingAnnotation @interface S {} 29866b415a2066cac9f36ed58070777de388f63a3a4crazyboblee} 299