Struts2依赖注入联系关系的类
Struts2依赖注入关联的类
// ContainerImpl 中定义的静态内部类
/** * Injects a field or method in a given object. */ interface Injector extends Serializable { void inject(InternalContext context, Object o); } static class MissingDependencyException extends Exception { MissingDependencyException(String message) { super(message); } }
// 一些Injector 的实现类
static class FieldInjector implements Injector { final Field field; final InternalFactory<?> factory; final ExternalContext<?> externalContext; public FieldInjector(ContainerImpl container, Field field, String name) throws MissingDependencyException { this.field = field; field.setAccessible(true);// 此处貌似都是有必要的 //不使用构造函数是因为 Key类中构造函数定义为private Key<?> key = Key.newInstance(field.getType(), name); factory = container.getFactory(key);//注意传入ContainerImpl呀! if (factory == null) { throw new MissingDependencyException( "No mapping found for dependency " + key + " in " + field + "."); } //不使用构造函数不知道为何了????? this.externalContext = ExternalContext.newInstance(field, key, container); } // 此处是核心关键调用的方法 public void inject(InternalContext context, Object o) { ExternalContext<?> previous = context.getExternalContext(); context.setExternalContext(externalContext); try { // 将指定对象变量上(o)此 Field 对象表示的字段设置为指定的新值(param2)。 field.set(o, factory.create(context)); } catch (IllegalAccessException e) { throw new AssertionError(e); } finally { // 此处谁能告诉我是干什么的? context.setExternalContext(previous); } } }
//
static class ParameterInjector<T> { final ExternalContext<T> externalContext; final InternalFactory<? extends T> factory; public ParameterInjector(ExternalContext<T> externalContext, InternalFactory<? extends T> factory) { this.externalContext = externalContext; this.factory = factory; } //member 反映有关单个成员(字段或方法)或构造方法的标识信息。 T inject(Member member, InternalContext context) { ExternalContext<?> previous = context.getExternalContext(); context.setExternalContext(externalContext); try { return factory.create(context); } finally { // 此处又来了 context.setExternalContext(previous); } } }
static class ConstructorInjector<T> { final Class<T> implementation; final List<Injector> injectors; final Constructor<T> constructor; final ParameterInjector<?>[] parameterInjectors; ConstructorInjector(ContainerImpl container, Class<T> implementation) { this.implementation = implementation; //内部类提供的内部方法 constructor = findConstructorIn(implementation); constructor.setAccessible(true); //也来了 try { Inject inject = constructor.getAnnotation(Inject.class); parameterInjectors = inject == null ? null // default constructor. : container.getParametersInjectors( constructor, constructor.getParameterAnnotations(), constructor.getParameterTypes(), inject.value() ); } catch (MissingDependencyException e) { throw new DependencyException(e); } injectors = container.injectors.get(implementation); } //内部类中提供的方法 @SuppressWarnings("unchecked") private Constructor<T> findConstructorIn(Class<T> implementation) { Constructor<T> found = null; Constructor<T>[] declaredConstructors = (Constructor<T>[]) implementation.getDeclaredConstructors(); for(Constructor<T> constructor : declaredConstructors) { if (constructor.getAnnotation(Inject.class) != null) { if (found != null) { throw new DependencyException("More than one constructor annotated" + " with @Inject found in " + implementation + "."); } found = constructor; } } if (found != null) { return found; } // If no annotated constructor is found, look for a no-arg constructor // instead. try { return implementation.getDeclaredConstructor(); } catch (NoSuchMethodException e) { throw new DependencyException("Could not find a suitable constructor" + " in " + implementation.getName() + "."); } } /** * Construct an instance. Returns {@code Object} instead of {@code T} * because it may return a proxy. */ Object construct(InternalContext context, Class<? super T> expectedType) { ConstructionContext<T> constructionContext = context.getConstructionContext(this); // We have a circular reference between constructors. Return a proxy. if (constructionContext.isConstructing()) { // TODO (crazybob): if we can't proxy this object, can we proxy the // other object? return constructionContext.createProxy(expectedType); } // If we're re-entering this factory while injecting fields or methods, // return the same instance. This prevents infinite loops. T t = constructionContext.getCurrentReference(); if (t != null) { return t; } try { // First time through... constructionContext.startConstruction(); try { Object[] parameters = getParameters(constructor, context, parameterInjectors); t = constructor.newInstance(parameters); constructionContext.setProxyDelegates(t); } finally { constructionContext.finishConstruction(); } // Store reference. If an injector re-enters this factory, they'll // get the same reference. constructionContext.setCurrentReference(t); // Inject fields and methods. for (Injector injector : injectors) { injector.inject(context, t); } return t; } catch (InstantiationException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } finally { constructionContext.removeCurrentReference(); } } }
// Container接口实现类中需要 重要的变量定义和方法定义
ThreadLocal<Object[]> localContext = new ThreadLocal<Object[]>() { protected InternalContext[] initialValue() { return new InternalContext[1]; } }; /** * Looks up thread local context. Creates (and removes) a new context if * necessary. */ <T> T callInContext(ContextualCallable<T> callable) { InternalContext[] reference = (InternalContext[]) localContext.get(); if (reference[0] == null) { reference[0] = new InternalContext(this); try { return callable.call(reference[0]); } finally { // Only remove the context if this call created it. reference[0] = null; } } else { // Someone else will clean up this context. return callable.call(reference[0]); } } // 注意此处的接口定义 interface ContextualCallable<T> { T call(InternalContext context); }