1 16 17 package com.google.inject; 18 19 import java.lang.reflect.InvocationHandler ; 20 import java.lang.reflect.InvocationTargetException ; 21 import java.lang.reflect.Method ; 22 import java.lang.reflect.Proxy ; 23 import java.util.ArrayList ; 24 import java.util.List ; 25 26 31 class ConstructionContext<T> { 32 33 T currentReference; 34 boolean constructing; 35 36 List <DelegatingInvocationHandler<T>> invocationHandlers; 37 38 T getCurrentReference() { 39 return currentReference; 40 } 41 42 void removeCurrentReference() { 43 this.currentReference = null; 44 } 45 46 void setCurrentReference(T currentReference) { 47 this.currentReference = currentReference; 48 } 49 50 boolean isConstructing() { 51 return constructing; 52 } 53 54 void startConstruction() { 55 this.constructing = true; 56 } 57 58 void finishConstruction() { 59 this.constructing = false; 60 invocationHandlers = null; 61 } 62 63 Object createProxy(Class <?> expectedType) { 64 68 if (!expectedType.isInterface()) { 69 throw new ConfigurationException("Tried proxying " 71 + expectedType.getName() + " to support a circular dependency, but" 72 + " it is not an interface."); 73 } 74 75 if (invocationHandlers == null) { 76 invocationHandlers = new ArrayList <DelegatingInvocationHandler<T>>(); 77 } 78 79 DelegatingInvocationHandler<T> invocationHandler 80 = new DelegatingInvocationHandler<T>(); 81 invocationHandlers.add(invocationHandler); 82 83 Object object = Proxy.newProxyInstance(expectedType.getClassLoader(), 84 new Class [] { expectedType }, invocationHandler); 85 return expectedType.cast(object); 86 } 87 88 void setProxyDelegates(T delegate) { 89 if (invocationHandlers != null) { 90 for (DelegatingInvocationHandler<T> handler : invocationHandlers) { 91 handler.setDelegate(delegate); 92 } 93 } 94 } 95 96 static class DelegatingInvocationHandler<T> implements InvocationHandler { 97 98 T delegate; 99 100 public Object invoke(Object proxy, Method method, Object [] args) 101 throws Throwable { 102 if (delegate == null) { 103 throw new IllegalStateException ("This is a proxy used to support" 104 + " circular references involving constructors. The object we're" 105 + " proxying is not constructed yet. Please wait until after" 106 + " injection has completed to use this object."); 107 } 108 109 try { 110 return method.invoke(delegate, args); 112 } 113 catch (IllegalAccessException e) { 114 throw new RuntimeException (e); 115 } 116 catch (IllegalArgumentException e) { 117 throw new RuntimeException (e); 118 } 119 catch (InvocationTargetException e) { 120 throw e.getTargetException(); 121 } 122 } 123 124 void setDelegate(T delegate) { 125 this.delegate = delegate; 126 } 127 } 128 } 129 | Popular Tags |