Slide 1

Slide 1 text

DI:依存性注入ライブラリを 自分で作ろう Benoît Quenaudon @oldergod

Slide 2

Slide 2 text

public class VisitHandler { private final Counter counter; private final Logger logger; public VisitHandler(Counter counter, Logger logger) { this.counter = counter; this.logger = logger; } public void visit() { counter.increment(); logger.log("Visits increased: " + counter.getCount()); } }

Slide 3

Slide 3 text

public class Counter { private int count; void increment() { count++; } int getCount() { return count; } } public class Logger { private final PrintStream printStream; public Logger(PrintStream printStream) { this.printStream = printStream; } public void log(String log) { printStream.println(log); } }

Slide 4

Slide 4 text

public static void main(String... args) { Counter counter = new Counter(); PrintStream printStream = System.out; Logger logger = new Logger(printStream); VisitHandler visitHandler = new VisitHandler(counter, logger); visitHandler.visit(); }

Slide 5

Slide 5 text

public static void main(String... args) { Counter counter = new Counter(); PrintStream printStream = System.out; Logger logger = new Logger(printStream); VisitHandler visitHandler = new VisitHandler(counter, logger); visitHandler.visit(); }

Slide 6

Slide 6 text

public static void main(String... args) { Counter counter = new Counter(); PrintStream printStream = System.out; Logger logger = new Logger(printStream); VisitHandler visitHandler = new VisitHandler(counter, logger); visitHandler.visit(); }

Slide 7

Slide 7 text

public static void main(String... args) { Counter counter = new Counter(); PrintStream printStream = System.out; Logger logger = new Logger(printStream); VisitHandler visitHandler = new VisitHandler(counter, logger); visitHandler.visit(); }

Slide 8

Slide 8 text

public static void main(String... args) { Counter counter = new Counter(); PrintStream printStream = System.out; Logger logger = new Logger(printStream); VisitHandler visitHandler = new VisitHandler(counter, logger); visitHandler.visit(); }

Slide 9

Slide 9 text

public static void main(String... args) { Counter counter = new Counter(); PrintStream printStream = System.out; Logger logger = new Logger(printStream); VisitHandler visitHandler = new VisitHandler(counter, logger); visitHandler.visit(); }

Slide 10

Slide 10 text

public static void main(String... args) { ObjectGraph objectGraph = buildObjectGraph(); VisitHandler visitHandler = objectGraph.get(VisitHandler.class); visitHandler.visit(); }

Slide 11

Slide 11 text

public class ObjectGraph { public T get(Class key) { throw new UnsupportedOperationException("Not implemented"); } }

Slide 12

Slide 12 text

public interface Factory { T get(Linker linker); } public class Linker { private final Map, Factory>> factories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { return (Factory) factories.get(key); } }

Slide 13

Slide 13 text

public interface Factory { T get(Linker linker); } public class Linker { private final Map, Factory>> factories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { return (Factory) factories.get(key); } }

Slide 14

Slide 14 text

public interface Factory { T get(Linker linker); } public class Linker { private final Map, Factory>> factories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { return (Factory) factories.get(key); } }

Slide 15

Slide 15 text

public interface Factory { T get(Linker linker); } public class Linker { private final Map, Factory>> factories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { return (Factory) factories.get(key); } }

Slide 16

Slide 16 text

public interface Factory { T get(Linker linker); } public class Linker { private final Map, Factory>> factories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { return (Factory) factories.get(key); } }

Slide 17

Slide 17 text

public class ObjectGraph { private final Linker linker; public ObjectGraph(Linker linker) { this.linker = linker; } public T get(Class key) { Factory factory = linker.factoryFor(key); return factory.get(linker); } }

Slide 18

Slide 18 text

public class ObjectGraph { private final Linker linker; public ObjectGraph(Linker linker) { this.linker = linker; } public T get(Class key) { Factory factory = linker.factoryFor(key); return factory.get(linker); } }

Slide 19

Slide 19 text

public static void main(String... args) { ObjectGraph objectGraph = buildObjectGraph(); VisitHandler visitHandler = objectGraph.get(VisitHandler.class); visitHandler.visit(); }

Slide 20

Slide 20 text

private static ObjectGraph buildObjectGraph() { Linker linker = new Linker(); installFactories(linker); return new ObjectGraph(linker); }

Slide 21

Slide 21 text

private static void installFactories(Linker linker) { linker.install(VisitHandler.class, ...); }

Slide 22

Slide 22 text

private static void installFactories(Linker linker) { linker.install(VisitHandler.class, new Factory() { @Override public VisitHandler get(Linker linker) { Factory counterFactory = linker.factoryFor(Counter.class); Factory loggerFactory = linker.factoryFor(Logger.class); Counter counter = counterFactory.get(linker); Logger logger = loggerFactory.get(linker); return new VisitHandler(counter, logger); } }); }

Slide 23

Slide 23 text

private static void installFactories(Linker linker) { linker.install(VisitHandler.class, new Factory() { @Override public VisitHandler get(Linker linker) { Factory counterFactory = linker.factoryFor(Counter.class); Factory loggerFactory = linker.factoryFor(Logger.class); Counter counter = counterFactory.get(linker); Logger logger = loggerFactory.get(linker); return new VisitHandler(counter, logger); } }); }

Slide 24

Slide 24 text

private static void installFactories(Linker linker) { linker.install(VisitHandler.class, new Factory() { @Override public VisitHandler get(Linker linker) { Factory counterFactory = linker.factoryFor(Counter.class); Factory loggerFactory = linker.factoryFor(Logger.class); Counter counter = counterFactory.get(linker); Logger logger = loggerFactory.get(linker); return new VisitHandler(counter, logger); } }); }

Slide 25

Slide 25 text

private static void installFactories(Linker linker) { linker.install(VisitHandler.class, new Factory() { @Override public VisitHandler get(Linker linker) { Factory counterFactory = linker.factoryFor(Counter.class); Factory loggerFactory = linker.factoryFor(Logger.class); Counter counter = counterFactory.get(linker); Logger logger = loggerFactory.get(linker); return new VisitHandler(counter, logger); } }); }

Slide 26

Slide 26 text

private static void installFactories(Linker linker) { linker.install(VisitHandler.class, new Factory() { @Override public VisitHandler get(Linker linker) { Factory counterFactory = linker.factoryFor(Counter.class); Factory loggerFactory = linker.factoryFor(Logger.class); Counter counter = counterFactory.get(linker); Logger logger = loggerFactory.get(linker); return new VisitHandler(counter, logger); } }); linker.install(Logger.class, new Factory() { @Override public Logger get(Linker linker) { Factory printStreamFactory = linker.factoryFor(PrintStream.class); PrintStream printStream = printStreamFactory.get(linker); return new Logger(printStreamFactory.get(linker)); } }); linker.install(PrintStream.class, new Factory() {

Slide 27

Slide 27 text

Factory loggerFactory = linker.factoryFor(Logger.class); Counter counter = counterFactory.get(linker); Logger logger = loggerFactory.get(linker); return new VisitHandler(counter, logger); } }); linker.install(Logger.class, new Factory() { @Override public Logger get(Linker linker) { Factory printStreamFactory = linker.factoryFor(PrintStream.class); PrintStream printStream = printStreamFactory.get(linker); return new Logger(printStreamFactory.get(linker)); } }); linker.install(PrintStream.class, new Factory() { @Override public PrintStream get(Linker linker) { return System.out; } }); linker.install(Counter.class, new Factory() {

Slide 28

Slide 28 text

Factory loggerFactory = linker.factoryFor(Logger.class); Counter counter = counterFactory.get(linker); Logger logger = loggerFactory.get(linker); return new VisitHandler(counter, logger); } }); linker.install(Logger.class, new Factory() { @Override public Logger get(Linker linker) { Factory printStreamFactory = linker.factoryFor(PrintStream.class); PrintStream printStream = printStreamFactory.get(linker); return new Logger(printStreamFactory.get(linker)); } }); linker.install(PrintStream.class, new Factory() { @Override public PrintStream get(Linker linker) { return System.out; } }); linker.install(Counter.class, new Factory() {

Slide 29

Slide 29 text

Factory loggerFactory = linker.factoryFor(Logger.class); Counter counter = counterFactory.get(linker); Logger logger = loggerFactory.get(linker); return new VisitHandler(counter, logger); } }); linker.install(Logger.class, new Factory() { @Override public Logger get(Linker linker) { Factory printStreamFactory = linker.factoryFor(PrintStream.class); PrintStream printStream = printStreamFactory.get(linker); return new Logger(printStreamFactory.get(linker)); } }); linker.install(PrintStream.class, new Factory() { @Override public PrintStream get(Linker linker) { return System.out; } }); linker.install(Counter.class, new Factory() {

Slide 30

Slide 30 text

linker.install(Logger.class, new Factory() { @Override public Logger get(Linker linker) { Factory printStreamFactory = linker.factoryFor(PrintStream.class); PrintStream printStream = printStreamFactory.get(linker); return new Logger(printStreamFactory.get(linker)); } }); linker.install(PrintStream.class, new Factory() { @Override public PrintStream get(Linker linker) { return System.out; } }); linker.install(Counter.class, new Factory() { @Override public Counter get(Linker linker) { return new Counter(); } }); }

Slide 31

Slide 31 text

linker.install(Logger.class, new Factory() { @Override public Logger get(Linker linker) { Factory printStreamFactory = linker.factoryFor(PrintStream.class); PrintStream printStream = printStreamFactory.get(linker); return new Logger(printStreamFactory.get(linker)); } }); linker.install(PrintStream.class, ValueFactory.of(System.out)); linker.install(Counter.class, new Factory() { @Override public Counter get(Linker linker) { return new Counter(); } }); }

Slide 32

Slide 32 text

public class ValueFactory implements Factory { public static Factory of(T instance) { return new ValueFactory<>(instance); } private final T value; public ValueFactory(T value) { this.value = value; } @Override public T get(Linker linker) { return value; } }

Slide 33

Slide 33 text

Logger logger = loggerFactory.get(linker); return new VisitHandler(counter, logger); } }); linker.install(Logger.class, new Factory() { @Override public Logger get(Linker linker) { Factory printStreamFactory = linker.factoryFor(PrintStream.class); PrintStream printStream = printStreamFactory.get(linker); return new Logger(printStreamFactory.get(linker)); } }); linker.install(PrintStream.class, ValueFactory.of(System.out)); linker.install(Counter.class, new Factory() { @Override public Counter get(Linker linker) { return new Counter(); } }); }

Slide 34

Slide 34 text

Logger logger = loggerFactory.get(linker); return new VisitHandler(counter, logger); } }); linker.install(Logger.class, new Factory() { @Override public Logger get(Linker linker) { Factory printStreamFactory = linker.factoryFor(PrintStream.class); PrintStream printStream = printStreamFactory.get(linker); return new Logger(printStreamFactory.get(linker)); } }); linker.install(PrintStream.class, ValueFactory.of(System.out)); linker.install(Counter.class, new Factory() { @Override public Counter get(Linker linker) { return new Counter(); } }); }

Slide 35

Slide 35 text

Logger logger = loggerFactory.get(linker); return new VisitHandler(counter, logger); } }); linker.install(Logger.class, new Factory() { @Override public Logger get(Linker linker) { Factory printStreamFactory = linker.factoryFor(PrintStream.class); PrintStream printStream = printStreamFactory.get(linker); return new Logger(printStreamFactory.get(linker)); } }); linker.install(PrintStream.class, ValueFactory.of(System.out)); linker.install(Counter.class, SingletonFactory.of(new Factory() { @Override public Counter get(Linker linker) { return new Counter(); } })); }

Slide 36

Slide 36 text

public class SingletonFactory implements Factory { public static Factory of(Factory factory) { return new SingletonFactory<>(factory); } private final Factory factory; private T instance; public SingletonFactory(Factory factory) { this.factory = factory; } @Override public T get(Linker linker) { if (instance == null) { instance = factory.get(linker); } return instance; } }

Slide 37

Slide 37 text

public class SingletonFactory implements Factory { public static Factory of(Factory factory) { return new SingletonFactory<>(factory); } private final Factory factory; private T instance; public SingletonFactory(Factory factory) { this.factory = factory; } @Override public T get(Linker linker) { if (instance == null) { instance = factory.get(linker); } return instance; } }

Slide 38

Slide 38 text

Logger logger = loggerFactory.get(linker); return new VisitHandler(counter, logger); } }); linker.install(Logger.class, new Factory() { @Override public Logger get(Linker linker) { Factory printStreamFactory = linker.factoryFor(PrintStream.class); PrintStream printStream = printStreamFactory.get(linker); return new Logger(printStreamFactory.get(linker)); } }); linker.install(PrintStream.class, ValueFactory.of(System.out)); linker.install(Counter.class, SingletonFactory.of(new Factory() { @Override public Counter get(Linker linker) { return new Counter(); } })); }

Slide 39

Slide 39 text

private static void installFactories(Linker linker) { linker.install(VisitHandler.class, new Factory() { @Override public VisitHandler get(Linker linker) { Factory counterFactory = linker.factoryFor(Counter.class); Factory loggerFactory = linker.factoryFor(Logger.class); Counter counter = counterFactory.get(linker); Logger logger = loggerFactory.get(linker); return new VisitHandler(counter, logger); } }); linker.install(Logger.class, new Factory() { @Override public Logger get(Linker linker) { Factory printStreamFactory = linker.factoryFor(PrintStream.class); PrintStream printStream = printStreamFactory.get(linker); return new Logger(printStream); } }); linker.install(PrintStream.class, ValueFactory.of(System.out)); linker.install(Counter.class, SingletonFactory.of(new Factory() { @Override public Counter get(Linker linker) { return new Counter(); } })); }

Slide 40

Slide 40 text

public class Linker { private final Map, Factory>> factories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { System.out.println("Get factory for " + key); return (Factory) factories.get(key); } }

Slide 41

Slide 41 text

public class Linker { private final Map, Factory>> factories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { System.out.println("Get factory for " + key); return (Factory) factories.get(key); } }

Slide 42

Slide 42 text

public static void main(String... args) { ObjectGraph objectGraph = buildObjectGraph(); VisitHandler visitHandler = objectGraph.get(VisitHandler.class); visitHandler.visit(); } Get factory for class VisitHandler Get factory for class Counter Get factory for class Logger Get factory for class java.io.PrintStream Visits increased: 1

Slide 43

Slide 43 text

So far ● Instantiation and its order automated

Slide 44

Slide 44 text

Good Job !

Slide 45

Slide 45 text

public static void main(String... args) { ObjectGraph objectGraph = buildObjectGraph(); VisitHandler visitHandler = objectGraph.get(VisitHandler.class); visitHandler.visit(); VisitHandler visitHandler2 = objectGraph.get(VisitHandler.class); visitHandler2.visit(); } Get factory for class VisitHandler Get factory for class Counter Get factory for class Logger Get factory for class java.io.PrintStream Visits increased: 1 Get factory for class VisitHandler Get factory for class Counter Get factory for class Logger Get factory for class java.io.PrintStream Visits increased: 2

Slide 46

Slide 46 text

public interface Factory { T get(Linker linker); }

Slide 47

Slide 47 text

public abstract class Factory { public void link(Linker linker) { } public abstract T get(); }

Slide 48

Slide 48 text

public class Linker { private final Map, Factory>> factories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { return (Factory) factories.get(key); } }

Slide 49

Slide 49 text

public class Linker { private final Map, Factory>> factories = new HashMap<>(); private final Map, Factory>> linkedFactories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { Factory> factory = linkedFactories.get(key); if (factory == null) { factory = factories.get(key); factory.link(this); linkedFactories.put(key, factory); } return (Factory) factory; } }

Slide 50

Slide 50 text

public class Linker { private final Map, Factory>> factories = new HashMap<>(); private final Map, Factory>> linkedFactories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { Factory> factory = linkedFactories.get(key); if (factory == null) { factory = factories.get(key); factory.link(this); linkedFactories.put(key, factory); } return (Factory) factory; } }

Slide 51

Slide 51 text

public class Linker { private final Map, Factory>> factories = new HashMap<>(); private final Map, Factory>> linkedFactories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { Factory> factory = linkedFactories.get(key); if (factory == null) { factory = factories.get(key); factory.link(this); linkedFactories.put(key, factory); } return (Factory) factory; } }

Slide 52

Slide 52 text

public class Linker { private final Map, Factory>> factories = new HashMap<>(); private final Map, Factory>> linkedFactories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { Factory> factory = linkedFactories.get(key); if (factory == null) { factory = factories.get(key); factory.link(this); linkedFactories.put(key, factory); } return (Factory) factory; } }

Slide 53

Slide 53 text

public class Linker { private final Map, Factory>> factories = new HashMap<>(); private final Map, Factory>> linkedFactories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { Factory> factory = linkedFactories.get(key); if (factory == null) { factory = factories.get(key); factory.link(this); linkedFactories.put(key, factory); } return (Factory) factory; } }

Slide 54

Slide 54 text

public class Linker { private final Map, Factory>> factories = new HashMap<>(); private final Map, Factory>> linkedFactories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { Factory> factory = linkedFactories.get(key); if (factory == null) { factory = factories.get(key); factory.link(this); linkedFactories.put(key, factory); } return (Factory) factory; } }

Slide 55

Slide 55 text

public class Linker { private final Map, Factory>> factories = new HashMap<>(); private final Map, Factory>> linkedFactories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { Factory> factory = linkedFactories.get(key); if (factory == null) { factory = factories.get(key); factory.link(this); linkedFactories.put(key, factory); } return (Factory) factory; } }

Slide 56

Slide 56 text

private static void installFactories(Linker linker) { linker.install(VisitHandler.class, new Factory() { @Override public VisitHandler get(Linker linker) { Factory counterFactory = linker.factoryFor(Counter.class); Factory loggerFactory = linker.factoryFor(Logger.class); Counter counter = counterFactory.get(linker); Logger logger = loggerFactory.get(linker); return new VisitHandler(counter, logger); } }); linker.install(Logger.class, new Factory() { @Override public Logger get(Linker linker) { Factory printStreamFactory = linker.factoryFor(PrintStream.class); PrintStream printStream = printStreamFactory.get(linker); return new Logger(printStream); } }); linker.install(PrintStream.class, ValueFactory.of(System.out)); linker.install(Counter.class, SingletonFactory.of(new Factory() { @Override public Counter get(Linker linker) { return new Counter(); } })); }

Slide 57

Slide 57 text

private static void installFactories(Linker linker) { linker.install(VisitHandler.class, new Factory() { @Override public VisitHandler get(Linker linker) { Factory counterFactory = linker.factoryFor(Counter.class); Factory loggerFactory = linker.factoryFor(Logger.class); Counter counter = counterFactory.get(linker); Logger logger = loggerFactory.get(linker); return new VisitHandler(counter, logger); } }); linker.install(Logger.class, new Factory() { @Override public Logger get(Linker linker) { Factory printStreamFactory = linker.factoryFor(PrintStream.class); PrintStream printStream = printStreamFactory.get(linker); return new Logger(printStream); } }); linker.install(PrintStream.class, ValueFactory.of(System.out));

Slide 58

Slide 58 text

private static void installFactories(Linker linker) { linker.install(VisitHandler.class, new Factory() { Factory loggerFactory; Factory counterFactory; @Override public void link(Linker linker) { counterFactory = linker.factoryFor(Counter.class); loggerFactory = linker.factoryFor(Logger.class); } @Override public VisitHandler get() { return new VisitHandler(counterFactory.get(), loggerFactory.get()); } }); linker.install(Logger.class, new Factory() { @Override public Logger get(Linker linker) { Factory printStreamFactory = linker.factoryFor(PrintStream.class); PrintStream printStream = printStreamFactory.get(linker);

Slide 59

Slide 59 text

private static void installFactories(Linker linker) { linker.install(VisitHandler.class, new Factory() { Factory loggerFactory; Factory counterFactory; @Override public void link(Linker linker) { counterFactory = linker.factoryFor(Counter.class); loggerFactory = linker.factoryFor(Logger.class); } @Override public VisitHandler get() { return new VisitHandler(counterFactory.get(), loggerFactory.get()); } }); linker.install(Logger.class, new Factory() { @Override public Logger get(Linker linker) { Factory printStreamFactory = linker.factoryFor(PrintStream.class); PrintStream printStream = printStreamFactory.get(linker);

Slide 60

Slide 60 text

private static void installFactories(Linker linker) { linker.install(VisitHandler.class, new Factory() { Factory loggerFactory; Factory counterFactory; @Override public void link(Linker linker) { counterFactory = linker.factoryFor(Counter.class); loggerFactory = linker.factoryFor(Logger.class); } @Override public VisitHandler get() { return new VisitHandler(counterFactory.get(), loggerFactory.get()); } }); linker.install(Logger.class, new Factory() { @Override public Logger get(Linker linker) { Factory printStreamFactory = linker.factoryFor(PrintStream.class); PrintStream printStream = printStreamFactory.get(linker);

Slide 61

Slide 61 text

private static void installFactories(Linker linker) { linker.install(VisitHandler.class, new Factory() { Factory loggerFactory; Factory counterFactory; @Override public void link(Linker linker) { counterFactory = linker.factoryFor(Counter.class); loggerFactory = linker.factoryFor(Logger.class); } @Override public VisitHandler get() { return new VisitHandler(counterFactory.get(), loggerFactory.get()); } }); linker.install(Logger.class, new Factory() { @Override public Logger get(Linker linker) { Factory printStreamFactory = linker.factoryFor(PrintStream.class); PrintStream printStream = printStreamFactory.get(linker);

Slide 62

Slide 62 text

public class Linker { private final Map, Factory>> factories = new HashMap<>(); private final Map, Factory>> linkedFactories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { System.out.println("Get factory for " + key); Factory> factory = linkedFactories.get(key); if (factory == null) { System.out.println("Link factory for " + key); factory = factories.get(key); factory.link(this); linkedFactories.put(key, factory); } return (Factory) factory; } }

Slide 63

Slide 63 text

public class Linker { private final Map, Factory>> factories = new HashMap<>(); private final Map, Factory>> linkedFactories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { System.out.println("Get factory for " + key); Factory> factory = linkedFactories.get(key); if (factory == null) { System.out.println("Link factory for " + key); factory = factories.get(key); factory.link(this); linkedFactories.put(key, factory); } return (Factory) factory; } }

Slide 64

Slide 64 text

Get factory for class VisitHandler Link factory for class VisitHandler Get factory for class Counter Link factory for class Counter Get factory for class Logger Link factory for class Logger Get factory for class java.io.PrintStream Link factory for class java.io.PrintStream Visits increased: 1 Get factory for class VisitHandler Visits increased: 2 public static void main(String... args) { ObjectGraph objectGraph = buildObjectGraph(); VisitHandler visitHandler = objectGraph.get(VisitHandler.class); visitHandler.visit(); VisitHandler visitHandler2 = objectGraph.get(VisitHandler.class); visitHandler2.visit(); }

Slide 65

Slide 65 text

So far ● Instantiation and its order automated ● Caching

Slide 66

Slide 66 text

Good Job !

Slide 67

Slide 67 text

private static void installFactories(Linker linker) { linker.install(VisitHandler.class, new Factory() { Factory loggerFactory; Factory counterFactory; @Override public void link(Linker linker) { counterFactory = linker.factoryFor(Counter.class); loggerFactory = linker.factoryFor(Logger.class); } @Override public VisitHandler get() { return new VisitHandler(counterFactory.get(), loggerFactory.get()); } }); linker.install(Logger.class, new Factory() { Factory printStreamFactory; @Override public void link(Linker linker) { printStreamFactory = linker.factoryFor(PrintStream.class); } @Override public Logger get() { return new Logger(printStreamFactory.get()); } }); linker.install(PrintStream.class, ValueFactory.of(System.out)); linker.install(Counter.class, SingletonFactory.of(new Factory() { @Override public Counter get() { return new Counter(); } })); }

Slide 68

Slide 68 text

public class VisitHandler { private final Counter counter; private final Logger logger; @Inject public VisitHandler(Counter counter, Logger logger) { this.counter = counter; this.logger = logger; } public void visit() { counter.increment(); logger.log("Visits increased: " + counter.getCount()); } }

Slide 69

Slide 69 text

public class VisitHandler { private final Counter counter; private final Logger logger; @Inject public VisitHandler(Counter counter, Logger logger) { this.counter = counter; this.logger = logger; } public void visit() { counter.increment(); logger.log("Visits increased: " + counter.getCount()); } }

Slide 70

Slide 70 text

public class Linker { private final Map, Factory>> factories = new HashMap<>(); private final Map, Factory>> linkedFactories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { Factory> factory = linkedFactories.get(key); if (factory == null) { factory = factories.get(key); factory.link(this); linkedFactories.put(key, factory); } return (Factory) factory; } }

Slide 71

Slide 71 text

public class Linker { private final Map, Factory>> factories = new HashMap<>(); private final Map, Factory>> linkedFactories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { Factory> factory = linkedFactories.get(key); if (factory == null) { factory = factories.get(key); factory.link(this); linkedFactories.put(key, factory); } return (Factory) factory; } }

Slide 72

Slide 72 text

public class Linker { private final Map, Factory>> factories = new HashMap<>(); private final Map, Factory>> linkedFactories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { Factory> factory = linkedFactories.get(key); if (factory == null) { factory = loadFactory(key); factory.link(this); linkedFactories.put(key, factory); } return (Factory) factory; } }

Slide 73

Slide 73 text

public class Linker { private final Map, Factory>> factories = new HashMap<>(); private final Map, Factory>> linkedFactories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { Factory> factory = linkedFactories.get(key); if (factory == null) { factory = loadFactory(key); factory.link(this); linkedFactories.put(key, factory); } return (Factory) factory; } }

Slide 74

Slide 74 text

private Factory> loadFactory(Class key) { Factory> factory = factories.get(key); if (factory != null) { return factory; } Constructor constructor = findAtInjectConstructor(key); if (constructor != null) { factory = new ReflectiveFactory(constructor); if (key.isAnnotationPresent(Singleton.class)) { factory = SingletonFactory.of(factory); } return factory; } throw new IllegalStateException("No factory for " + key); } private Constructor findAtInjectConstructor(Class type) { for (Constructor> constructor : type.getConstructors()) { if (constructor.isAnnotationPresent(Inject.class)) { return (Constructor) constructor; } } return null; }

Slide 75

Slide 75 text

No content

Slide 76

Slide 76 text

private Factory> loadFactory(Class key) { Factory> factory = factories.get(key); if (factory != null) { return factory; } Constructor constructor = findAtInjectConstructor(key); if (constructor != null) { factory = new ReflectiveFactory(constructor); if (key.isAnnotationPresent(Singleton.class)) { factory = SingletonFactory.of(factory); } return factory; } throw new IllegalStateException("No factory for " + key); } private Constructor findAtInjectConstructor(Class type) { for (Constructor> constructor : type.getConstructors()) { if (constructor.isAnnotationPresent(Inject.class)) { return (Constructor) constructor; } } return null; }

Slide 77

Slide 77 text

private Factory> loadFactory(Class key) { Factory> factory = factories.get(key); if (factory != null) { return factory; } Constructor constructor = findAtInjectConstructor(key); if (constructor != null) { factory = new ReflectiveFactory(constructor); if (key.isAnnotationPresent(Singleton.class)) { factory = SingletonFactory.of(factory); } return factory; } throw new IllegalStateException("No factory for " + key); } private Constructor findAtInjectConstructor(Class type) { for (Constructor> constructor : type.getConstructors()) { if (constructor.isAnnotationPresent(Inject.class)) { return (Constructor) constructor; } } return null; }

Slide 78

Slide 78 text

private Factory> loadFactory(Class key) { Factory> factory = factories.get(key); if (factory != null) { return factory; } Constructor constructor = findAtInjectConstructor(key); if (constructor != null) { factory = new ReflectiveFactory(constructor); if (key.isAnnotationPresent(Singleton.class)) { factory = SingletonFactory.of(factory); } return factory; } throw new IllegalStateException("No factory for " + key); } private Constructor findAtInjectConstructor(Class type) { for (Constructor> constructor : type.getConstructors()) { if (constructor.isAnnotationPresent(Inject.class)) { return (Constructor) constructor; } } return null; }

Slide 79

Slide 79 text

private Factory> loadFactory(Class key) { Factory> factory = factories.get(key); if (factory != null) { return factory; } Constructor constructor = findAtInjectConstructor(key); if (constructor != null) { factory = new ReflectiveFactory(constructor); if (key.isAnnotationPresent(Singleton.class)) { factory = SingletonFactory.of(factory); } return factory; } throw new IllegalStateException("No factory for " + key); } private Constructor findAtInjectConstructor(Class type) { for (Constructor> constructor : type.getConstructors()) { if (constructor.isAnnotationPresent(Inject.class)) { return (Constructor) constructor; } } return null; }

Slide 80

Slide 80 text

private Factory> loadFactory(Class key) { Factory> factory = factories.get(key); if (factory != null) { return factory; } Constructor constructor = findAtInjectConstructor(key); if (constructor != null) { factory = new ReflectiveFactory(constructor); if (key.isAnnotationPresent(Singleton.class)) { factory = SingletonFactory.of(factory); } return factory; } throw new IllegalStateException("No factory for " + key); } private Constructor findAtInjectConstructor(Class type) { for (Constructor> constructor : type.getConstructors()) { if (constructor.isAnnotationPresent(Inject.class)) { return (Constructor) constructor; } } return null; }

Slide 81

Slide 81 text

private Factory> loadFactory(Class key) { Factory> factory = factories.get(key); if (factory != null) { return factory; } Constructor constructor = findAtInjectConstructor(key); if (constructor != null) { factory = new ReflectiveFactory(constructor); if (key.isAnnotationPresent(Singleton.class)) { factory = SingletonFactory.of(factory); } return factory; } throw new IllegalStateException("No factory for " + key); } private Constructor findAtInjectConstructor(Class type) { for (Constructor> constructor : type.getConstructors()) { if (constructor.isAnnotationPresent(Inject.class)) { return (Constructor) constructor; } } return null; }

Slide 82

Slide 82 text

public class ReflectiveFactory extends Factory { private final Constructor constructor; private final ArrayList> factories = new ArrayList<>(); public ReflectiveFactory(Constructor constructor) { this.constructor = constructor; } @Override public void link(Linker linker) { for (Class> parameterType : constructor.getParameterTypes()) { factories.add(linker.factoryFor(parameterType)); } } @Override public T get() { Object[] dependencies = new Object[factories.size()]; for (int i = 0; i < dependencies.length; i++) { Factory> factory = factories.get(i); dependencies[i] = factory.get(); } try { return constructor.newInstance(dependencies); } catch (Exception e) { throw new RuntimeException(e); } } }

Slide 83

Slide 83 text

public class ReflectiveFactory extends Factory { private final Constructor constructor; private final ArrayList> factories = new ArrayList<>(); public ReflectiveFactory(Constructor constructor) { this.constructor = constructor; } @Override public void link(Linker linker) { for (Class> parameterType : constructor.getParameterTypes()) { factories.add(linker.factoryFor(parameterType)); } } @Override public T get() { Object[] dependencies = new Object[factories.size()]; for (int i = 0; i < dependencies.length; i++) { Factory> factory = factories.get(i); dependencies[i] = factory.get(); } try { return constructor.newInstance(dependencies); } catch (Exception e) { throw new RuntimeException(e); } } }

Slide 84

Slide 84 text

public class ReflectiveFactory extends Factory { private final Constructor constructor; private final ArrayList> factories = new ArrayList<>(); public ReflectiveFactory(Constructor constructor) { this.constructor = constructor; } @Override public void link(Linker linker) { for (Class> parameterType : constructor.getParameterTypes()) { factories.add(linker.factoryFor(parameterType)); } } @Override public T get() { Object[] dependencies = new Object[factories.size()]; for (int i = 0; i < dependencies.length; i++) { Factory> factory = factories.get(i); dependencies[i] = factory.get(); } try { return constructor.newInstance(dependencies); } catch (Exception e) { throw new RuntimeException(e); } } }

Slide 85

Slide 85 text

public class ReflectiveFactory extends Factory { private final Constructor constructor; private final ArrayList> factories = new ArrayList<>(); public ReflectiveFactory(Constructor constructor) { this.constructor = constructor; } @Override public void link(Linker linker) { for (Class> parameterType : constructor.getParameterTypes()) { factories.add(linker.factoryFor(parameterType)); } } @Override public T get() { Object[] dependencies = new Object[factories.size()]; for (int i = 0; i < dependencies.length; i++) { Factory> factory = factories.get(i); dependencies[i] = factory.get(); } try { return constructor.newInstance(dependencies); } catch (Exception e) { throw new RuntimeException(e); } } }

Slide 86

Slide 86 text

public class ReflectiveFactory extends Factory { private final Constructor constructor; private final ArrayList> factories = new ArrayList<>(); public ReflectiveFactory(Constructor constructor) { this.constructor = constructor; } @Override public void link(Linker linker) { for (Class> parameterType : constructor.getParameterTypes()) { factories.add(linker.factoryFor(parameterType)); } } @Override public T get() { Object[] dependencies = new Object[factories.size()]; for (int i = 0; i < dependencies.length; i++) { Factory> factory = factories.get(i); dependencies[i] = factory.get(); } try { return constructor.newInstance(dependencies); } catch (Exception e) { throw new RuntimeException(e); } } }

Slide 87

Slide 87 text

public class VisitHandler { @Inject public VisitHandler(Counter counter, Logger logger) { this.counter = counter; this.logger = logger; } } public class Logger { @Inject public Logger(PrintStream printStream) { this.printStream = printStream; } } @Singleton public class Counter { @Inject public Counter() {} }

Slide 88

Slide 88 text

private static void installFactories(Linker linker) { linker.install(VisitHandler.class, new Factory() { Factory loggerFactory; Factory counterFactory; @Override public void link(Linker linker) { counterFactory = linker.factoryFor(Counter.class); loggerFactory = linker.factoryFor(Logger.class); } @Override public VisitHandler get() { return new VisitHandler(counterFactory.get(), loggerFactory.get()); } }); linker.install(Logger.class, new Factory() { Factory printStreamFactory; @Override public void link(Linker linker) { printStreamFactory = linker.factoryFor(PrintStream.class); } @Override public Logger get() { return new Logger(printStreamFactory.get()); } }); linker.install(PrintStream.class, ValueFactory.of(System.out)); linker.install(Counter.class, SingletonFactory.of(new Factory() { @Override public Counter get() { return new Counter(); } })); }

Slide 89

Slide 89 text

private static void installFactories(Linker linker) { linker.install(VisitHandler.class, new Factory() { ... }); linker.install(Logger.class, new Factory() { ... }); linker.install(PrintStream.class, ValueFactory.of(System.out)); linker.install(Counter.class, SingletonFactory.of(new Factory() { ... })); }

Slide 90

Slide 90 text

private static void installFactories(Linker linker) { linker.install(Logger.class, new Factory() { ... }); linker.install(PrintStream.class, ValueFactory.of(System.out)); linker.install(Counter.class, SingletonFactory.of(new Factory() { ... })); }

Slide 91

Slide 91 text

private static void installFactories(Linker linker) { linker.install(PrintStream.class, ValueFactory.of(System.out)); linker.install(Counter.class, SingletonFactory.of(new Factory() { ... })); }

Slide 92

Slide 92 text

private static void installFactories(Linker linker) { linker.install(PrintStream.class, ValueFactory.of(System.out)); }

Slide 93

Slide 93 text

private static void installFactories(Linker linker) { linker.install(VisitHandler.class, new Factory() { Factory loggerFactory; Factory counterFactory; @Override public void link(Linker linker) { counterFactory = linker.factoryFor(Counter.class); loggerFactory = linker.factoryFor(Logger.class); } @Override public VisitHandler get() { return new VisitHandler(counterFactory.get(), loggerFactory.get()); } }); linker.install(Logger.class, new Factory() { Factory printStreamFactory; @Override public void link(Linker linker) { printStreamFactory = linker.factoryFor(PrintStream.class); } @Override public Logger get() { return new Logger(printStreamFactory.get()); } }); linker.install(PrintStream.class, ValueFactory.of(System.out)); linker.install(Counter.class, SingletonFactory.of(new Factory() { @Override public Counter get() { return new Counter(); } })); } private static void installFactories(Linker linker) { linker.install(PrintStream.class, ValueFactory.of(System.out)); }

Slide 94

Slide 94 text

So far ● Instantiation and its order automated ● Caching ● No boilerplate

Slide 95

Slide 95 text

No content

Slide 96

Slide 96 text

Good Job !

Slide 97

Slide 97 text

No content

Slide 98

Slide 98 text

linker.install(VisitHandler.class, new Factory() { Factory printStreamFactory; @Override public void link(Linker linker) { printStreamFactory = linker.factoryFor(PrintStream.class); } @Override public Logger get() { return new Logger(printStreamFactory.get()); } });

Slide 99

Slide 99 text

Annotation Processing

Slide 100

Slide 100 text

public class Logger$$Factory extends Factory { Factory printStreamFactory; @Override public void link(Linker linker) { printStreamFactory = linker.factoryFor(PrintStream.class); } @Override public Logger get() { return new Logger(printStreamFactory.get()); } }

Slide 101

Slide 101 text

public abstract class GeneratedFactory extends Factory { private final boolean singleton; public GeneratedFactory(boolean singleton) { this.singleton = singleton; } } public class Logger$$Factory extends GeneratedFactory { public Logger$$Factory() { super(false); } }

Slide 102

Slide 102 text

private Factory> loadFactory(Class key) { Factory> factory = factories.get(key); if (factory != null) { return factory; } Constructor constructor = findAtInjectConstructor(key); if (constructor != null) { factory = new ReflectiveFactory(constructor); if (key.isAnnotationPresent(Singleton.class)) { factory = SingletonFactory.of(factory); } return factory; } throw new IllegalStateException("No factory for " + key); }

Slide 103

Slide 103 text

public class Linker { private Factory> loadFactory(Class key) { Factory> factory = factories.get(key); if (factory != null) { return factory; } factory = GeneratedFactory.loadFactory(key); if (factory != null) { return factory; } throw new IllegalStateException("No factory for " + key); } }

Slide 104

Slide 104 text

public class Linker { private Factory> loadFactory(Class key) { Factory> factory = factories.get(key); if (factory != null) { return factory; } factory = GeneratedFactory.loadFactory(key); if (factory != null) { return factory; } throw new IllegalStateException("No factory for " + key); } }

Slide 105

Slide 105 text

public abstract class GeneratedFactory extends Factory { public static Factory loadFactory(Class key) { String generatedClass = key.getName() + "$$Factory"; try { Class> factoryClass = (Class>) Class.forName(generatedClass); GeneratedFactory factory = factoryClass.newInstance(); if (factory.singleton) { return SingletonFactory.of(factory); } else { return factory; } } catch (Exception e) { System.err.println("Error for " + key); e.printStackTrace(); return null; } } private final boolean singleton; public GeneratedFactory(boolean singleton) { this.singleton = singleton; } }

Slide 106

Slide 106 text

public abstract class GeneratedFactory extends Factory { public static Factory loadFactory(Class key) { String generatedClass = key.getName() + "$$Factory"; try { Class> factoryClass = (Class>) Class.forName(generatedClass); GeneratedFactory factory = factoryClass.newInstance(); if (factory.singleton) { return SingletonFactory.of(factory); } else { return factory; } } catch (Exception e) { System.err.println("Error for " + key); e.printStackTrace(); return null; } } private final boolean singleton; public GeneratedFactory(boolean singleton) { this.singleton = singleton; } }

Slide 107

Slide 107 text

public abstract class GeneratedFactory extends Factory { public static Factory loadFactory(Class key) { String generatedClass = key.getName() + "$$Factory"; try { Class> factoryClass = (Class>) Class.forName(generatedClass); GeneratedFactory factory = factoryClass.newInstance(); if (factory.singleton) { return SingletonFactory.of(factory); } else { return factory; } } catch (Exception e) { System.err.println("Error for " + key); e.printStackTrace(); return null; } } private final boolean singleton; public GeneratedFactory(boolean singleton) { this.singleton = singleton; } }

Slide 108

Slide 108 text

So far ● Instantiation and its order automated ● Caching ● No boilerplate ● No reflection

Slide 109

Slide 109 text

BETA

Slide 110

Slide 110 text

Good Job !

Slide 111

Slide 111 text

public class DatabaseManager { private final Database database; @Inject public DatabaseManager(Database database) { this.database = database; } public void updateVisits(int count) { database.execute("UPDATE count_table SET count = " + count); } }

Slide 112

Slide 112 text

public static void main(String... args) { ObjectGraph objectGraph = buildObjectGraph(); DatabaseManager databaseManager = objectGraph.get(DatabaseManager.class); databaseManager.updateVisits(3); } Exception in thread "main" java.lang.IllegalStateException: No factory for interface app.db.Database at injection.Linker.loadFactory(Linker.java:41) at injection.Linker.factoryFor(Linker.java:21) at app.db.DatabaseManager$$Factory.link(DatabaseManager$$Factory.java:17) at injection.factory.SingletonFactory.link(SingletonFactory.java:20) at injection.Linker.factoryFor(Linker.java:22) at injection.ObjectGraph.get(ObjectGraph.java:13) at Main.main(Main.java:11)

Slide 113

Slide 113 text

public static void main(String... args) { ObjectGraph objectGraph = buildObjectGraph(); objectGraph.validate(DatabaseManager.class); DatabaseManager databaseManager = objectGraph.get(DatabaseManager.class); databaseManager.updateVisits(3); } public class ObjectGraph { private final Linker linker; public T get(Class key) { Factory factory = linker.factoryFor(key); return factory.get(); } public void validate(Class key) { linker.factoryFor(key); } }

Slide 114

Slide 114 text

public static void main(String... args) { ObjectGraph objectGraph = buildObjectGraph(); objectGraph.validate(DatabaseManager.class); DatabaseManager databaseManager = objectGraph.get(DatabaseManager.class); databaseManager.updateVisits(3); } public class ObjectGraph { private final Linker linker; public T get(Class key) { Factory factory = linker.factoryFor(key); return factory.get(); } public void validate(Class key) { linker.factoryFor(key); } }

Slide 115

Slide 115 text

static void installFactories(Linker linker) { linker.install(PrintStream.class, ValueFactory.of(System.out)); }

Slide 116

Slide 116 text

public static void main(String... args) { ObjectGraph objectGraph = buildObjectGraph(); objectGraph.validate(DatabaseManager.class); // … } public static void installFactories(Linker linker) { linker.install(PrintStream.class, ValueFactory.of(System.out)); }

Slide 117

Slide 117 text

Annotation Processing

Slide 118

Slide 118 text

public static void main(String... args) { ObjectGraph objectGraph = buildObjectGraph(); objectGraph.validate(DatabaseManager.class); // … } public static void installFactories(Linker linker) { linker.install(PrintStream.class, ValueFactory.of(System.out)); }

Slide 119

Slide 119 text

public class Module { @Provides public Database provideDatabase(DatabaseImpl database) { return database; } @Provides public PrintStream providePrintStream() { return System.out; } }

Slide 120

Slide 120 text

public class Module { @Provides public Database provideDatabase(DatabaseImpl database) { return database; } @Provides public PrintStream providePrintStream() { return System.out; } }

Slide 121

Slide 121 text

@Module public class MainModule { @Provides public Database provideDatabase(DatabaseImpl database) { return database; } @Provides public PrintStream providePrintStream() { return System.out; } }

Slide 122

Slide 122 text

private static ObjectGraph buildObjectGraph() { Linker linker = new Linker(); installFactories(linker); return new ObjectGraph(linker); } private static void installFactories(Linker linker) { linker.install(PrintStream.class, ValueFactory.of(System.out)); }

Slide 123

Slide 123 text

private static ObjectGraph buildObjectGraph(List moduleClasses) { Linker linker = new Linker(); linker.loadModuleBindings(moduleClasses); return new ObjectGraph(linker); } private static void installFactories(Linker linker) { linker.install(PrintStream.class, ValueFactory.of(System.out)); }

Slide 124

Slide 124 text

public static void main(String... args) { ObjectGraph objectGraph = buildObjectGraph(); objectGraph.validate(DatabaseManager.class); // … }

Slide 125

Slide 125 text

@Module public class MainModule { @Provides public Database provideDatabase(DatabaseImpl database) { return database; } @Provides public PrintStream providePrintStream() { return System.out; } }

Slide 126

Slide 126 text

@Module public class MainModule { @Provides public Database provideDatabase(DatabaseImpl database) { return database; } @Provides public PrintStream providePrintStream() { return System.out; } }

Slide 127

Slide 127 text

@Module(injects = DatabaseManager.class) public class MainModule { @Provides public Database provideDatabase(DatabaseImpl database) { return database; } @Provides public PrintStream providePrintStream() { return System.out; } }

Slide 128

Slide 128 text

So far ● Instantiation and its order automated ● Caching ● No boilerplate ● No reflection ● Verification at compile time

Slide 129

Slide 129 text

No content

Slide 130

Slide 130 text

Good Job !

Slide 131

Slide 131 text

Object Graph Linker @Singleton Factory Factory @Singleton Factory VisitHandler Database Manager Counter

Slide 132

Slide 132 text

Object Graph Linker @Singleton Factory Factory @Singleton Factory VisitHandler Database Manager Counter

Slide 133

Slide 133 text

Object Graph @Singleton Database Manager @Singleton Counter

Slide 134

Slide 134 text

Object Graph @Singleton Database Manager @Singleton Counter

Slide 135

Slide 135 text

Object Graph @Singleton Database Manager @Singleton Counter Object Graph

Slide 136

Slide 136 text

Object Graph @Singleton Database Manager @Singleton Counter Object Graph

Slide 137

Slide 137 text

Object Graph @Singleton Database Manager @Singleton Counter Object Graph Object Graph @Singleton App

Slide 138

Slide 138 text

Object Graph @Singleton Database Manager @Singleton Counter Object Graph Object Graph @Singleton App

Slide 139

Slide 139 text

@Singleton Database Manager Object Graph Object Graph @Singleton App

Slide 140

Slide 140 text

Object Graph @Singleton Database Manager @Singleton Counter Object Graph Object Graph @Singleton App

Slide 141

Slide 141 text

Scoped Instance

Slide 142

Slide 142 text

public class ObjectGraph { final Linker linker; final ObjectGraph parentGraph; public T get(Class key) { if (parentGraph != null) { T instance = parentGraph.get(key); if (instance != null) { return instance; } } Factory factory = linker.factoryFor(key); return factory.get(); } }

Slide 143

Slide 143 text

public class ObjectGraph { final Linker linker; final ObjectGraph parentGraph; public T get(Class key) { if (parentGraph != null) { T instance = parentGraph.get(key); if (instance != null) { return instance; } } Factory factory = linker.factoryFor(key); return factory.get(); } }

Slide 144

Slide 144 text

public class ObjectGraph { final Linker linker; final ObjectGraph parentGraph; public T get(Class key) { if (parentGraph != null) { T instance = parentGraph.get(key); if (instance != null) { return instance; } } Factory factory = linker.factoryFor(key); return factory.get(); } }

Slide 145

Slide 145 text

public class ObjectGraph { final Linker linker; final ObjectGraph parentGraph; public T get(Class key) { if (parentGraph != null) { T instance = parentGraph.get(key); if (instance != null) { return instance; } } Factory factory = linker.factoryFor(key); return factory.get(); } }

Slide 146

Slide 146 text

public class Linker { private final Map, Factory>> factories = new HashMap<>(); private final Map, Factory>> linkedFactories = new HashMap<>(); public void install(Class key, Factory factory) { factories.put(key, factory); } public Factory factoryFor(Class key) { Factory> factory = linkedFactories.get(key); if (factory == null) { factory = loadFactory(key); factory.link(this); linkedFactories.put(key, factory); } return (Factory) factory; } }

Slide 147

Slide 147 text

So far ● Instantiation and its order automated ● Caching ● No boilerplate ● No reflection ● Verification at compile time ● Scope

Slide 148

Slide 148 text

Good Job !

Slide 149

Slide 149 text

public class Logger$$Factory extends GeneratedFactory { private Factory printStreamFactory; public Logger$$Factory() {} @Override public void link(Linker linker) { printStreamFactory = linker.factoryFor(PrintStream.class); } @Override public Logger get() { return new Logger(printStreamFactory.get()); } }

Slide 150

Slide 150 text

public class Logger$$Factory extends GeneratedFactory { private Factory printStreamFactory; public Logger$$Factory() {} @Override public Logger get() { return new Logger(printStreamFactory.get()); } }

Slide 151

Slide 151 text

public class Logger$$Factory extends GeneratedFactory { private final Factory printStreamFactory; public Logger$$Factory(Factory printStreamFactory) { this.printStreamFactory = printStreamFactory; } @Override public Logger get() { return new Logger(printStreamFactory.get()); } }

Slide 152

Slide 152 text

@Module(injects = DatabaseManager.class) public class MainModule { @Provides public Database provideDatabase(DatabaseImpl database) { return database; } @Provides public PrintStream providePrintStream() { return System.out; } } @Component(modules = MainModule.class) public interface MainComponent { DatabaseManager databaseManager(); }

Slide 153

Slide 153 text

@Module public class MainModule { @Provides public Database provideDatabase(DatabaseImpl database) { return database; } @Provides public PrintStream providePrintStream() { return System.out; } } @Component(modules = MainModule.class) public interface MainComponent { DatabaseManager databaseManager(); }

Slide 154

Slide 154 text

public class DaggerMainComponent implements MainComponent { Factory printStreamFactory; Factory loggerFactory; Factory databaseManagerFactory; public DaggerMainComponent() { final MainModule mainModule = new MainModule(); printStreamFactory = new Factory() { @Override public PrintStream get() { return mainModule.providePrintStream(); } }; loggerFactory = new Logger$$Factory(printStreamFactory); databaseManagerFactory = new DatabaseManager$$Factory(loggerFactory); } @Override public DatabaseManager databaseManager() { return databaseManagerFactory.get(); } }

Slide 155

Slide 155 text

public class DaggerMainComponent implements MainComponent { Factory printStreamFactory; Factory loggerFactory; Factory databaseManagerFactory; public DaggerMainComponent() { final MainModule mainModule = new MainModule(); printStreamFactory = new Factory() { @Override public PrintStream get() { return mainModule.providePrintStream(); } }; loggerFactory = new Logger$$Factory(printStreamFactory); databaseManagerFactory = new DatabaseManager$$Factory(loggerFactory); } @Override public DatabaseManager databaseManager() { return databaseManagerFactory.get(); } }

Slide 156

Slide 156 text

public class DaggerMainComponent implements MainComponent { Factory printStreamFactory; Factory loggerFactory; Factory databaseManagerFactory; public DaggerMainComponent() { final MainModule mainModule = new MainModule(); printStreamFactory = new Factory() { @Override public PrintStream get() { return mainModule.providePrintStream(); } }; loggerFactory = new Logger$$Factory(printStreamFactory); databaseManagerFactory = new DatabaseManager$$Factory(loggerFactory); } @Override public DatabaseManager databaseManager() { return databaseManagerFactory.get(); } }

Slide 157

Slide 157 text

public class DaggerMainComponent implements MainComponent { Factory printStreamFactory; Factory loggerFactory; Factory databaseManagerFactory; public DaggerMainComponent() { final MainModule mainModule = new MainModule(); printStreamFactory = new Factory() { @Override public PrintStream get() { return mainModule.providePrintStream(); } }; loggerFactory = new Logger$$Factory(printStreamFactory); databaseManagerFactory = new DatabaseManager$$Factory(loggerFactory); } @Override public DatabaseManager databaseManager() { return databaseManagerFactory.get(); } }

Slide 158

Slide 158 text

public class DaggerMainComponent implements MainComponent { Factory printStreamFactory; Factory loggerFactory; Factory databaseManagerFactory; public DaggerMainComponent() { final MainModule mainModule = new MainModule(); printStreamFactory = new Factory() { @Override public PrintStream get() { return mainModule.providePrintStream(); } }; loggerFactory = new Logger$$Factory(printStreamFactory); databaseManagerFactory = new DatabaseManager$$Factory(loggerFactory); } @Override public DatabaseManager databaseManager() { return databaseManagerFactory.get(); } }

Slide 159

Slide 159 text

DatabaseManager databaseManager = new DaggerMainComponent().databaseManager();

Slide 160

Slide 160 text

So far ● Instantiation and its order automated ● Caching ● No boilerplate ● No reflection ● Verification at compile time ● Scope ● Great performance

Slide 161

Slide 161 text

2

Slide 162

Slide 162 text

Good Job !

Slide 163

Slide 163 text

Fin Slides: goo.gl/nceQmc Benoît Quenaudon @oldergod

Slide 164

Slide 164 text

Reference ● DIY: Build Your Own Dependency Injection Library ○ https://news.realm.io/news/android-pierre-yves-ricau-build-own-dependency-injection/ ● Dagger ○ https://google.github.io/dagger