1/** 2 * Copyright (C) 2009 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.google.inject.internal; 18 19import static com.google.common.collect.Iterables.concat; 20 21import com.google.common.collect.ImmutableList; 22import com.google.inject.spi.InjectionPoint; 23 24/** 25 * Constructor injectors by type. 26 * 27 * @author jessewilson@google.com (Jesse Wilson) 28 */ 29final class ConstructorInjectorStore { 30 private final InjectorImpl injector; 31 32 private final FailableCache<InjectionPoint, ConstructorInjector<?>> cache 33 = new FailableCache<InjectionPoint, ConstructorInjector<?>> () { 34 @Override 35 protected ConstructorInjector<?> create(InjectionPoint constructorInjector, Errors errors) 36 throws ErrorsException { 37 return createConstructor(constructorInjector, errors); 38 } 39 }; 40 41 ConstructorInjectorStore(InjectorImpl injector) { 42 this.injector = injector; 43 } 44 45 /** 46 * Returns a new complete constructor injector with injection listeners registered. 47 */ 48 public ConstructorInjector<?> get(InjectionPoint constructorInjector, Errors errors) 49 throws ErrorsException { 50 return cache.get(constructorInjector, errors); 51 } 52 53 /** 54 * Purges an injection point from the cache. Use this only if the cache is not actually valid and 55 * needs to be purged. (See issue 319 and 56 * ImplicitBindingTest#testCircularJitBindingsLeaveNoResidue and 57 * #testInstancesRequestingProvidersForThemselvesWithChildInjectors for examples of when this is 58 * necessary.) 59 * 60 * Returns true if the injector for that point was stored in the cache, false otherwise. 61 */ 62 boolean remove(InjectionPoint ip) { 63 return cache.remove(ip); 64 } 65 66 private <T> ConstructorInjector<T> createConstructor(InjectionPoint injectionPoint, Errors errors) 67 throws ErrorsException { 68 int numErrorsBefore = errors.size(); 69 70 SingleParameterInjector<?>[] constructorParameterInjectors 71 = injector.getParametersInjectors(injectionPoint.getDependencies(), errors); 72 73 @SuppressWarnings("unchecked") // the injector type agrees with the injection point type 74 MembersInjectorImpl<T> membersInjector = (MembersInjectorImpl<T>) injector.membersInjectorStore 75 .get(injectionPoint.getDeclaringType(), errors); 76 77 /*if[AOP]*/ 78 ImmutableList<MethodAspect> injectorAspects = injector.state.getMethodAspects(); 79 ImmutableList<MethodAspect> methodAspects = membersInjector.getAddedAspects().isEmpty() 80 ? injectorAspects 81 : ImmutableList.copyOf(concat(injectorAspects, membersInjector.getAddedAspects())); 82 ConstructionProxyFactory<T> factory = new ProxyFactory<T>(injectionPoint, methodAspects); 83 /*end[AOP]*/ 84 /*if[NO_AOP] 85 ConstructionProxyFactory<T> factory = new DefaultConstructionProxyFactory<T>(injectionPoint); 86 end[NO_AOP]*/ 87 88 errors.throwIfNewErrors(numErrorsBefore); 89 90 return new ConstructorInjector<T>(membersInjector.getInjectionPoints(), factory.create(), 91 constructorParameterInjectors, membersInjector); 92 } 93} 94