1、首先Inject(com.opensymphony.xwork2.inject)这个Annotation类
这个类是对Inject的定义,其内容如下:
/**
* @Retention(RetentionPolicy.RUNTIME)在这里指定了注解保留的周期;有三个周期
* CLASS:编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释。
* RUNTIME:编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。
* SOURCE:编译器要丢弃的注释。
* @Target(ElementType.TYPE) 这个标识注解应该标在那里 ElementType的几个枚举值就代表了 注解应该写在的位置
* CONSTRUCTOR:构造方法声明
* FIELD:字段声明(包括枚举常量)
* LOCAL_VARIABLE: 局部变量声明
* METHOD:方法声明
* PACKAGE:包声明
* PARAMETER:参数声明
* TYPE: 类、接口(包括注释类型)或枚举声明
*/
@Target({METHOD, CONSTRUCTOR, FIELD, PARAMETER})
@Retention(RUNTIME)
public @interface Inject {
/**
* 依赖的名字. 默认为Struts2的Container中的DEFAULT_NAME(default).
*/
String value() default DEFAULT_NAME;
/**
* 是否必须注入.
*/
boolean required() default true;
}
2、Struts2内部的依赖注入核心参考《Struts2的IoC解析》
链接地址为:http://blog.youkuaiyun.com/yanlinwang/article/details/8944632
3、以下是对Struts2的个人理解
/**
* 默认Container的实现
*/
@SuppressWarnings("serial")
class ContainerImpl implements Container {
/**
* bean容器
*/
final Map<Key<?>, InternalFactory<?>> factories;
/**
* 定义一个类型到名称集合的映射关系,一个类型对应于多个名称
*/
final Map<Class<?>, Set<String>> factoryNamesByType;
/**
* 构造方法、在该方法中对factories和factoryNamesByType进行初始化
* @param factories
*/
ContainerImpl( Map<Key<?>, InternalFactory<?>> factories ) {
//初始化factories
this.factories = factories;
//一个类型对应于多个名称,构建一个类型到名称集合的映射关系
Map<Class<?>, Set<String>> map = new HashMap<Class<?>, Set<String>>();
/**
* 对factories进行遍历
*/
for ( Key<?> key : factories.keySet() ) {
Set<String> names = map.get(key.getType());
if (names == null) {
names = new HashSet<String>();
map.put(key.getType(), names);
}
names.add(key.getName());
}
/**
* 将名称集合固化为不可修改的
*/
for ( Entry<Class<?>, Set<String>> entry : map.entrySet() ) {
entry.setValue(Collections.unmodifiableSet(entry.getValue()));
}
//将类型到名称集合的映射关系固化为不可修改
this.factoryNamesByType = Collections.unmodifiableMap(map);
}
/**
* 根据KEY找到该类型的构造工厂类
* @param <T>
* @param key 类型
* @return
*/
@SuppressWarnings("unchecked")
<T> InternalFactory<? extends T> getFactory( Key<T> key ) {
return (InternalFactory<T>) factories.get(key);
}
/**
* 初始化一个注入器map,用来保存类和其注入器之间的关系
* 该变量是ReferenceCache的一个实例
*/
final Map<Class<?>, List<Injector>> injectors = new ReferenceCache<Class<?>, List<Injector>>() {
@Override
protected List<Injector> create( Class<?> key ) {
List<Injector> injectors = new ArrayList<Injector>();
addInjectors(key, injectors);//在这里对key进行依赖注入
return injectors;
}
};
/**
* 从给定的类中循环向给定的列表中注入变量和方法。父类在子类之前注入
*/
void addInjectors( Class clazz, List<Injector> injectors ) {
if (clazz == Object.class) {
return;
}
//向父类进行递归,为其父类进行依赖注入,直到遇到Object类为止
addInjectors(clazz.getSuperclass(), injectors);
// TODO (crazybob): Filter out overridden members.
/**
* 通过该方法,将需要注入的非静态属性放入injectors中
*/
addInjectorsForFields(clazz.getDeclaredFields(), false, injectors);
/**
* 通过该方法,将需要注入的非静态方法放入injectors中
*/
addInjectorsForMethods(clazz.getDeclaredMethods(), false, injectors);
}
/**
* 依赖注入(静态参数、方法)
* @param staticInjections
*/
void injectStatics( List<Class<?>> staticInjections ) {
final List<Injector> injectors = new ArrayList<Injector>();
/**
* 对参数staticInjections进行遍历
*/
for ( Class<?> clazz : staticInjections ) {
//class的getDeclaredFields()方法返回此 Class 对象所表示的类或接口所声明的所有字段
/**
* 通过该方法,将需要注入的静态属性放入injectors中
*/
addInjectorsForFields(clazz.getDeclaredFields(), true, injectors);
//class的getDeclaredMethods()方法返回此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
/**
* 通过该方法,将需要注入的静态方法放入injectors中
*/
addInjectorsForMethods(clazz.getDeclaredMethods(), true, injectors);
}
callInContext(new ContextualCallable<Void>() {
/**
* 实现该ContextualCallable接口中的call方法
*/
public Void call( InternalContext context ) {
for ( Injector injector : injectors ) {
injector.inject(context, null);
}
return null;
}
});
}
/**
* 找到对象所定义的全部方法,并且表示成注入器列表方式
* @param methods
* @param statics
* @param injectors
*/
void addInjectorsForMethods( Method[] methods, boolean statics, List<Injector> injectors ) {
addInjectorsForMembers(Arrays.asList(methods), statics, injectors,
new InjectorFactory<Method>() {
public Injector create( ContainerImpl container, Method method,
String name ) throws MissingDependencyException {
return new MethodInjector(container, method, name);
}
});
}
/**
* 找到对象所定义的全部字段,并且表示成注入器列表方式
* @param fields 某个类的所有属性
* @param statics false
* @param injectors
*/
void addInjectorsForFields( Field[] fields, boolean statics, List<Injector> injectors ) {
//Arrays.asList();返回一个受指定数组支持的固定大小的列表
addInjectorsForMembers(Arrays.asList(fields), statics, injectors,
new InjectorFactory<Field>() {
public Injector create( ContainerImpl container, Field field, String name ) throws MissingDependencyException {
return new FieldInjector(container, field, name);
}
});
}
/**
* 找到有注解@Inject的成员,调用传入的injectorFactory.create方法创建真正的Injector实例 加入到注入器集合中
* @param <M>
* @param members 参数或是方法列表
* @param statics
* @param injectors a new Object
* @param injectorFactory
*/
<M extends Member & AnnotatedElement> void addInjectorsForMembers(List<M> members, boolean statics, List<Injector> injectors, InjectorFactory<M> injectorFactory ) {
//对members对象进行遍历
for ( M member : members ) {
if (isStatic(member) == statics) {
//如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。
Inject inject = member.getAnnotation(Inject.class);
//这里inject.value()默认为default
if (inject != null) {
try {
injectors.add(injectorFactory.create(this, member, inject.value()));//把这个Member放入injectors中
} catch ( MissingDependencyException e ) {
if (inject.required()) {
throw new DependencyException(e);
}
}
}
}
}
}
/**
* 注入器工厂接口
* @author Administrator
*
* @param <M>
*/
interface InjectorFactory<M extends Member & AnnotatedElement> {
Injector create( ContainerImpl container, M member, String name ) throws MissingDependencyException;
}
/**
* 检查成员是否为静态的
* @param member
* @return
*/
private boolean isStatic( Member member ) {
//member.getModifiers()返回作为整数返回由此 Member 所表示的成员或构造方法的 Java 语言修饰符
//Modifier.isStatic()如果整数参数包括 static 修饰符,则返回 true,否则返回 false。
return Modifier.isStatic(member.getModifiers());
}
/**
* 字段属性注入器
* @author Administrator
*
*/
static class FieldInjector implements Injector {
final Field field;
//类加载的时候需要注入的成员
final InternalFactory<?> factory;
//运行时需要注入的成员
final ExternalContext<?> externalContext;
/**
* 属性注入构造器
* @param container 容器实例
* @param field 字段
* @param name 属性字段名称
* @throws MissingDependencyException
*/
public FieldInjector( ContainerImpl container, Field field, String name )throws MissingDependencyException {
this.field = field;//初始化field字段
//field.isAccessible获取此对象的 accessible 标志的值。
if (!field.isAccessible()) {
SecurityManager sm = System.getSecurityManager();
try {
if (sm != null) {
//如果基于当前有效的安全策略,不允许执行根据给定权限所指定的请求访问,则抛出 SecurityException。
//反射操作的 Permission 类。ReflectPermission 是一种指定权限,没有动作
sm.checkPermission(new ReflectPermission("suppressAccessChecks"));
}
//设定该字段的accessible
field.setAccessible(true);
} catch ( AccessControlException e ) {
throw new DependencyException("Security manager in use, could not access field: "
+ field.getDeclaringClass().getName() + "(" + field.getName() + ")", e);
}
}
//创建一个基于field的key的实例
Key<?> key = Key.newInstance(field.getType(), name);
//从当前的factory中获取该key的工厂类
factory = container.getFactory(key);
//如果不存在则抛出异常
if (factory == null) {
throw new MissingDependencyException(
"No mapping found for dependency " + key + " in " + field + ".");
}
//实例化一个externalContext
this.externalContext = ExternalContext.newInstance(field, key, container);
}
/**
* 将传入的对象的字段设置值
* @param context 内部上下文
* @param o 传入对象
*/
public void inject( InternalContext context, Object o ) {
ExternalContext<?> previous = context.getExternalContext();
context.setExternalContext(externalContext);
try {
field.set(o, factory.create(context));//对field进行赋值
} catch ( IllegalAccessException e ) {
throw new AssertionError(e);
} finally {
context.setExternalContext(previous);
}
}
}
/**
* 获取参数的injectors
*
* @param member 参数所属的Member
* @param annotations 参数上面的Annotation
* @param parameterTypes 参数类型
*
* @return injections
*/
<M extends AccessibleObject & Member> ParameterInjector<?>[]
getParametersInjectors( M member, Annotation[][] annotations, Class[] parameterTypes, String defaultName ) throws MissingDependencyException {
List<ParameterInjector<?>> parameterInjectors = new ArrayList<ParameterInjector<?>>();//创建一个新的ParameterInjector集合
Iterator<Annotation[]> annotationsIterator = Arrays.asList(annotations).iterator();//把annotations参数转换成Iterator对象
/**
* 对Iterator对象进行遍历
*/
for ( Class<?> parameterType : parameterTypes ) {
Inject annotation = findInject(annotationsIterator.next());//获取annotations参数中的Inject注解的Annotation
String name = annotation == null ? defaultName : annotation.value();//获取annotation的value
Key<?> key = Key.newInstance(parameterType, name);//将其组装成一个KEY
parameterInjectors.add(createParameterInjector(key, member));
}
return toArray(parameterInjectors);
}
/**
* 根据KEY从factories中获取该key的工厂类
* @param <T>
* @param key
* @param member
* @return
* @throws MissingDependencyException
*/
<T> ParameterInjector<T> createParameterInjector( Key<T> key, Member member ) throws MissingDependencyException {
InternalFactory<? extends T> factory = getFactory(key);//获取指定key的工厂类
/**
* 如果此工厂类不存在,则抛出异常
*/
if (factory == null) {
throw new MissingDependencyException("No mapping found for dependency " + key + " in " + member + ".");
}
ExternalContext<T> externalContext = ExternalContext.newInstance(member, key, this);
return new ParameterInjector<T>(externalContext, factory);//返回一个新的ParameterInjector对象
}
/**
* 把parameterInjector的集合转换成一个ParameterInjector的数组
* @param parameterInjections
* @return
*/
@SuppressWarnings("unchecked")
private ParameterInjector<?>[] toArray(List<ParameterInjector<?>> parameterInjections ) {
return parameterInjections.toArray(new ParameterInjector[parameterInjections.size()]);
}
/**
* 获取annotations参数中的Inject注解的Annotation
*/
Inject findInject( Annotation[] annotations ) {
for ( Annotation annotation : annotations ) {
if (annotation.annotationType() == Inject.class) {
return Inject.class.cast(annotation);
}
}
return null;
}
/**
* 方法注入器定义,负责以对象方法方式注入对象
* @author Administrator
*
*/
static class MethodInjector implements Injector {
/**
* 方法
*/
final Method method;
/**
* 参数注入器
*/
final ParameterInjector<?>[] parameterInjectors;
/**
* 默认构造方法,在该方法中初始化参数
* @param container
* @param method
* @param name
* @throws MissingDependencyException
*/
public MethodInjector( ContainerImpl container, Method method, String name ) throws MissingDependencyException {
//初始化method
this.method = method;
/**
* 对method进行包装
*/
if (!method.isAccessible()) {
SecurityManager sm = System.getSecurityManager();
try {
if (sm != null) {
sm.checkPermission(new ReflectPermission("suppressAccessChecks"));
}
method.setAccessible(true);
} catch ( AccessControlException e ) {
throw new DependencyException("Security manager in use, could not access method: "
+ name + "(" + method.getName() + ")", e);
}
}
//按照声明顺序返回 Class 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型。
Class<?>[] parameterTypes = method.getParameterTypes();
//如果此Method的所有的方法的形参类型为0,则抛出异常
if (parameterTypes.length == 0) {
throw new DependencyException(method + " has no parameters to inject.");
}
/**
* 获取形参的injector,该对象是ParameterInjector类型的数组
*/
parameterInjectors = container.getParametersInjectors(method, method.getParameterAnnotations(), parameterTypes, name);
}
/**
* 采用反射机制对方法进行注入
*/
public void inject( InternalContext context, Object o ) {
try {
/**
* 进行方法的依赖注入
*/
method.invoke(o, getParameters(method, context, parameterInjectors));
} catch ( Exception e ) {
throw new RuntimeException(e);
}
}
}
/**
* 构造方法的注入
*/
Map<Class<?>, ConstructorInjector> constructors = new ReferenceCache<Class<?>, ConstructorInjector>() {
@Override
@SuppressWarnings("unchecked")
protected ConstructorInjector<?> create( Class<?> implementation ) {
return new ConstructorInjector(ContainerImpl.this, implementation);
}
};
/**
* 构造函数注入器
* @author Administrator
*
* @param <T>
*/
static class ConstructorInjector<T> {
/**
* 要处理的类型
*/
final Class<T> implementation;
/**
* 需要注入的属性或者方法
*/
final List<Injector> injectors;
/**
* 构造器
*/
final Constructor<T> constructor;
/**
* 需要注入的参数数组
*/
final ParameterInjector<?>[] parameterInjectors;
/**
* 构造方法,在该方法中初始化implementation
* @param container
* @param implementation
*/
ConstructorInjector( ContainerImpl container, Class<T> implementation ) {
//初始化implementation
this.implementation = implementation;
constructor = findConstructorIn(implementation);
if (!constructor.isAccessible()) {
SecurityManager sm = System.getSecurityManager();
try {
if (sm != null) {
sm.checkPermission(new ReflectPermission("suppressAccessChecks"));
}
constructor.setAccessible(true);
} catch ( AccessControlException e ) {
throw new DependencyException("Security manager in use, could not access constructor: "
+ implementation.getName() + "(" + constructor.getName() + ")", e);
}
}
MissingDependencyException exception = null;
Inject inject = null;
ParameterInjector<?>[] parameters = null;
try {
//取得注解方式声明的注入依赖
inject = constructor.getAnnotation(Inject.class);
parameters = constructParameterInjector(inject, container, constructor);
} catch ( MissingDependencyException e ) {
exception = e;
}
parameterInjectors = parameters;
if (exception != null) {
if (inject != null && inject.required()) {
throw new DependencyException(exception);
}
}
injectors = container.injectors.get(implementation);
}
ParameterInjector<?>[] constructParameterInjector(
Inject inject, ContainerImpl container, Constructor<T> constructor ) throws MissingDependencyException {
return constructor.getParameterTypes().length == 0
? null // default constructor.
: container.getParametersInjectors(
constructor,
constructor.getParameterAnnotations(),
constructor.getParameterTypes(),
inject.value()
);
}
/**
* 找到类implementation的构造器
* @param implementation 要处理的类型
* @return
*/
@SuppressWarnings("unchecked")
private Constructor<T> findConstructorIn( Class<T> implementation ) {
Constructor<T> found = null;
Constructor<T>[] declaredConstructors = (Constructor<T>[]) implementation.getDeclaredConstructors();
/**
* 对获取的构造函数进行遍历,查找出添加了Annotation的构造函数
*/
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();
}
}
}
/**
* 参数注入器,表示以对象方法方式注入时的一个方法注入形式
* @author Administrator
*
* @param <T>
*/
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;
}
/**
* 创建一个需要注入到方法参数的对象
* @param member 方法
* @param context 内部上下文
* @return 构造号的参数对象
*/
T inject( Member member, InternalContext context ) {
ExternalContext<?> previous = context.getExternalContext();
context.setExternalContext(externalContext);
try {
/**
* 工厂类生成实例对象
*/
return factory.create(context);
} finally {
context.setExternalContext(previous);
}
}
}
/**
* 取得对象的方法的参数数组
* @param member 方法
* @param context 内部上下文
* @param parameterInjectors 参数的注入器数组
* @return 构造号的方法参数数组
*/
private static Object[] getParameters( Member member, InternalContext context, ParameterInjector[] parameterInjectors ) {
if (parameterInjectors == null) {
return null;
}
Object[] parameters = new Object[parameterInjectors.length];
/**
* 遍历参数,生成对象
*/
for ( int i = 0; i < parameters.length; i++ ) {
parameters[i] = parameterInjectors[i].inject(member, context);
}
return parameters;
}
/**
* 给对象注入其依赖的值或者对象
* @param o 需要注入属性或者对象的对象
* @param context 内部上下文
*/
void inject( Object o, InternalContext context ) {
List<Injector> injectors = this.injectors.get(o.getClass());
for ( Injector injector : injectors ) {
injector.inject(context, o);
}
}
/**
* 给对象注入其依赖的值或者对象
* @param <T>
* @param implementation
* @param context
* @return
*/
<T> T inject( Class<T> implementation, InternalContext context ) {
try {
ConstructorInjector<T> constructor = getConstructor(implementation);
return implementation.cast(constructor.construct(context, implementation));
} catch ( Exception e ) {
throw new RuntimeException(e);
}
}
/**
* 依照给定的类型和名称以及内部上下文创建对象的实例
* @param <T> 参数类型
* @param type 类型
* @param name 对象名称
* @param context 内部上下文
* @return
*/
@SuppressWarnings("unchecked")
<T> T getInstance( Class<T> type, String name, InternalContext context ) {
ExternalContext<?> previous = context.getExternalContext();
Key<T> key = Key.newInstance(type, name);
context.setExternalContext(ExternalContext.newInstance(null, key, this));
try {
InternalFactory o = getFactory(key);
if (o != null) {
return getFactory(key).create(context);
} else {
return null;
}
} finally {
context.setExternalContext(previous);
}
}
/**
* 依照给定的类型和默认名称以及内部上下文创建对象的实例
* @param <T> 参数类型
* @param type 类型
* @param context 内部上下文
* @return
*/
<T> T getInstance( Class<T> type, InternalContext context ) {
return getInstance(type, DEFAULT_NAME, context);
}
/**
* 注入依赖到已经存在的对象的字段和方法
*/
public void inject( final Object o ) {
callInContext(new ContextualCallable<Void>() {
public Void call( InternalContext context ) {
inject(o, context);
return null;
}
});
}
/**
* 创建并且注入一个新的对应类型的实例
*/
public <T> T inject( final Class<T> implementation ) {
return callInContext(new ContextualCallable<T>() {
public T call( InternalContext context ) {
return inject(implementation, context);
}
});
}
/**
* 取得类型的实例对象
*/
public <T> T getInstance( final Class<T> type, final String name ) {
return callInContext(new ContextualCallable<T>() {
public T call( InternalContext context ) {
return getInstance(type, name, context);
}
});
}
/**
* 根据默认名称来取得类型的实例对象(适用于一个类型创建一个默认对象的情况)
*/
public <T> T getInstance( final Class<T> type ) {
return callInContext(new ContextualCallable<T>() {
public T call( InternalContext context ) {
return getInstance(type, context);
}
});
}
/**
* 根据类型来取得该类型的实例对象名称集合(适用于同一个类型创建了多个不同名称的对象)
*/
public Set<String> getInstanceNames( final Class<?> type ) {
return factoryNamesByType.get(type);
}
/**
* 本地线程上下文,保存内部上下文对象
*/
ThreadLocal<Object[]> localContext =
new ThreadLocal<Object[]>() {
@Override
protected Object[] initialValue() {
return new Object[1];
}
};
/**
* 查找Thread Local的上下文。在必要的情况下,创建(或删除)一个上下文
* Looks up thread local context. Creates (and removes) a new context if necessary.
*/
<T> T callInContext( ContextualCallable<T> callable ) {
Object[] reference = localContext.get();//从localContext中获取此线程局部变量的当前线程副本中的值。
/**
* 如果其为空
*/
if (reference[0] == null) {
reference[0] = new InternalContext(this);//创建一个新的InternalContext对象赋值给reference[0]
try {
/**
* 调用callable中的call方法,并返回结果
*/
return callable.call((InternalContext) reference[0]);
} finally {
//如果reference[0]是新创建的话,则移除
reference[0] = null;
//同时情况localContext
localContext.remove();
}
} else {
//如果reference[0]不为空,则直接进行调用
return callable.call((InternalContext) reference[0]);
}
}
/**
* 内部定义的接口
* @author Administrator
*
* @param <T>
*/
interface ContextualCallable<T> {
T call( InternalContext context );
}
/**
* 根据给定的实现类来找到构造函数
* Gets a constructor function for a given implementation class.
*/
@SuppressWarnings("unchecked")
<T> ConstructorInjector<T> getConstructor( Class<T> implementation ) {
return constructors.get(implementation);
}
/**
* 作用域策略本地线程
*/
final ThreadLocal<Object> localScopeStrategy =
new ThreadLocal<Object>();
public void setScopeStrategy( Scope.Strategy scopeStrategy ) {
this.localScopeStrategy.set(scopeStrategy);
}
public void removeScopeStrategy() {
this.localScopeStrategy.remove();
}
/**
* 定义一个向对象中注入字段或者方法属性接口
*/
interface Injector extends Serializable {
void inject( InternalContext context, Object o );
}
static class MissingDependencyException extends Exception {
MissingDependencyException( String message ) {
super(message);
}
}
}