(PS:我終於搞明白 一點了 T-T 參考文章:https://www.cnblogs.com/huashui/p/3191886.html)
目錄
Container接口
package com.opensymphony.xwork2.inject;
public interface Container extends Serializable {
//默認對象識別標誌
String DEFAULT_NAME = "default";
//進行對象的依賴注入操作。o爲被注入對象的對象。意思就是完成o中@inject操作
void inject(Object var1);
//創建一個類的實例並進行對象的依賴注入操作
<T> T inject(Class<T> var1);
//通過type和name獲得實例
<T> T getInstance(Class<T> var1, String var2);
//通過type和默認的name獲得對象
<T> T getInstance(Class<T> var1);
//根據type獲取與這個type所對應的容器中的所有註冊過的name。
Set<String> getInstanceNames(Class<?> var1);
//設置當前線程的作用範圍的策略。
void setScopeStrategy(Strategy var1);
//刪除當前線程的作用範圍的策略。
void removeScopeStrategy();
}
從Container的源代碼可以看出,容器的作用有以下三點:
①,獲取對象實例。
②,對象的依賴注入。
③,處理對象的作用範圍策略。
其中最重要的是第一點和第二點。那麼,我們可以通過Container來獲取對象的實例,具體來說,哪些實例我們可以獲取到呢?
其實我們獲取的是xml配置文件中的bean節點的對象和constant節點的參數。
我們來看官方文檔對bean節點的解釋:
從官方的解釋可以看出,bean是被框架的容器創建的,並且被容器注入到框架內部對象中去。
其實從命名就可以看出來,inject就是注入的意思。當我們把某個對象實例作爲參數傳入到inject方法中時,框架會掃描該對象內部聲明有@Inject註解的字段,方法,構造函數或者是方法參數,並將它們注入容器中的管理對象。
因此,所謂struts2的依賴注入其實就是在需要被注入的字段,方法,構造函數或者方法參數上加上@Inject註解就可以了。
對象的注入依賴
具體進入ContainerImpl這個類看看,具體的實現我們就不細說了,看看關於injector和@inject主要的幾個方法和字段,弄明白爲什麼。(這對我來說已經很吃力了。)
package com.opensymphony.xwork2.inject;
class ContainerImpl implements Container {
//Key存儲的是<bean>中對應的type和name,InternalFactory可以理解爲工廠
final Map<Key<?>, InternalFactory<?>> factories;
//存儲tpye-names的映射
final Map<Class<?>, Set<String>> factoryNamesByType;
//注入器,可以注意到使用了ReferenceCache作爲緩存。具體的create方法之後說明
final Map<Class<?>, List<ContainerImpl.Injector>> injectors = new ReferenceCache<Class<?>, List<ContainerImpl.Injector>>() {
protected List<ContainerImpl.Injector> create(Class<?> key) {
List<ContainerImpl.Injector> injectors = new ArrayList();
ContainerImpl.this.addInjectors(key, injectors);
return injectors;
}
};
//構造方法上的注入器
Map<Class<?>, ContainerImpl.ConstructorInjector> constructors = new ReferenceCache<Class<?>, ContainerImpl.ConstructorInjector>() {
protected ContainerImpl.ConstructorInjector<?> create(Class<?> implementation) {
return new ContainerImpl.ConstructorInjector(ContainerImpl.this, implementation);
}
};
//ThreadLocal保證線程安全 一個是object數組、一個是object對象
ThreadLocal<Object[]> localContext = new ThreadLocal<Object[]>() {
protected Object[] initialValue() {
return new Object[1];
}
};
//構造函數,主要工作見註釋
ContainerImpl(Map<Key<?>, InternalFactory<?>> factories) {
this.factories = factories;
Map<Class<?>, Set<String>> map = new HashMap();
Iterator i$;
Key key;
Object names;
//合併相同type不同name的類
for(i$ = factories.keySet().iterator(); i$.hasNext(); ((Set)names).add(key.getName())) {
key = (Key)i$.next();
names = (Set)map.get(key.getType());
if (names == null) {
names = new HashSet();
map.put(key.getType(), names);
}
}
i$ = map.entrySet().iterator();
while(i$.hasNext()) {
Entry<Class<?>, Set<String>> entry = (Entry)i$.next();
//不可更改的集合
entry.setValue(Collections.unmodifiableSet((Set)entry.getValue()));
}
//不可更改的k-v
this.factoryNamesByType = Collections.unmodifiableMap(map);
}
//添加註入器,遞歸調用,最終要調用到addInjectorsForMembers(..)
void addInjectors(Class clazz, List<ContainerImpl.Injector> injectors) {
if (clazz != Object.class) {
this.addInjectors(clazz.getSuperclass(), injectors);
//字段的注入器,即@inject註解作用的字段
this.addInjectorsForFields(clazz.getDeclaredFields(), false, injectors);
this.addInjectorsForMethods(clazz.getDeclaredMethods(), false, injectors);
}
}
//方法上的@inject注入器
void addInjectorsForMethods(Method[] methods, boolean statics, List<ContainerImpl.Injector> injectors) {
//最終調用的放法
this.addInjectorsForMembers(Arrays.asList(methods), statics, injectors, new ContainerImpl.InjectorFactory<Method>() {
public ContainerImpl.Injector create(ContainerImpl container, Method method, String name) throws ContainerImpl.MissingDependencyException {
return new ContainerImpl.MethodInjector(container, method, name);
}
});
}
//字段上的@inject注入器
void addInjectorsForFields(Field[] fields, boolean statics, List<ContainerImpl.Injector> injectors) {
this.addInjectorsForMembers(Arrays.asList(fields), statics, injectors, new ContainerImpl.InjectorFactory<Field>() {
public ContainerImpl.Injector create(ContainerImpl container, Field field, String name) throws ContainerImpl.MissingDependencyException {
return new ContainerImpl.FieldInjector(container, field, name);
}
});
}
//添加註入器成員,加入injectors中
<M extends Member & AnnotatedElement> void addInjectorsForMembers(List<M> members, boolean statics, List<ContainerImpl.Injector> injectors, ContainerImpl.InjectorFactory<M> injectorFactory) {
Iterator i$ = members.iterator();
while(true) {
Member member;
Inject inject;
do {
do {
if (!i$.hasNext()) {
return;
}
member = (Member)i$.next();
} while(this.isStatic(member) != statics);
inject = (Inject)((AnnotatedElement)member).getAnnotation(Inject.class);
} while(inject == null);
try {
injectors.add(injectorFactory.create(this, member, inject.value()));
} catch (ContainerImpl.MissingDependencyException var9) {
if (inject.required()) {
throw new DependencyException(var9);
}
}
}
}
//獲得方法參數的注入器
<M extends AccessibleObject & Member> ContainerImpl.ParameterInjector<?>[] getParametersInjectors(M member, Annotation[][] annotations, Class[] parameterTypes, String defaultName) throws ContainerImpl.MissingDependencyException {
}
//生成方法參數的注入器
<T> ContainerImpl.ParameterInjector<T> createParameterInjector(Key<T> key, Member member) throws ContainerImpl.MissingDependencyException {
}
//獲得被注入對象的實例,依次調用了ParameterInjector類的inject方法,注意到它並沒實現Injector接口
private static Object[] getParameters(Member member, InternalContext context, ContainerImpl.ParameterInjector[] parameterInjectors) {
if (parameterInjectors == null) {
return null;
} else {
Object[] parameters = new Object[parameterInjectors.length];
for(int i = 0; i < parameters.length; ++i) {
//需要注入的方法參數的值
parameters[i] = parameterInjectors[i].inject(member, context);
}
return parameters;
}
}
//完成對象o的依賴注入操作的對外接口
public void inject(final Object o) {
this.callInContext(new ContainerImpl.ContextualCallable<Void>() {
public Void call(InternalContext context) {
//內部實現的具體方法
ContainerImpl.this.inject(o, context);
return null;
}
});
}
//內部實現的具體方法
void inject(Object o, InternalContext context) {
//獲得注入對象o相同class的注入器
List<ContainerImpl.Injector> injectors = (List)this.injectors.get(o.getClass());
Iterator i$ = injectors.iterator();
//將該對象o通過注入器注入
while(i$.hasNext()) {
ContainerImpl.Injector injector = (ContainerImpl.Injector)i$.next();
//這裏我們可以看看具體的injector注入器類的inject方法
injector.inject(context, o);
}
}
//創建一個類的實例並進行對象的依賴注入操作,這裏就和構造函數有關了
public <T> T inject(final Class<T> implementation) {
return this.callInContext(new ContainerImpl.ContextualCallable<T>() {
public T call(InternalContext context) {
return ContainerImpl.this.inject(implementation, context);
}
});
}
//內部實現
<T> T inject(Class<T> implementation, InternalContext context) {
try {
//獲得該class的構造器
ContainerImpl.ConstructorInjector<T> constructor = this.getConstructor(implementation);
return implementation.cast(constructor.construct(context, implementation));
} catch (Exception var4) {
throw new RuntimeException(var4);
}
}
//這個類我還不太清楚什麼作用,請求的上下文?
<T> T callInContext(ContainerImpl.ContextualCallable<T> callable) {
Object[] reference = (Object[])this.localContext.get();
if (reference[0] == null) {
reference[0] = new InternalContext(this);
Object var3;
try {
//一般會執行這一句
var3 = callable.call((InternalContext)reference[0]);
} finally {
reference[0] = null;
this.localContext.remove();
}
return var3;
} else {
return callable.call((InternalContext)reference[0]);
}
}
//注入器統一的接口
interface Injector extends Serializable {
void inject(InternalContext var1, Object var2);
}
interface ContextualCallable<T> {
T call(InternalContext var1);
}
//字段注入器
static class FieldInjector implements ContainerImpl.Injector {}
//方法注入器
static class MethodInjector implements ContainerImpl.Injector {}
//參數注入器
static class ParameterInjector<T> {}
//構造方法注入器
static class ConstructorInjector<T> {}
interface InjectorFactory<M extends Member & AnnotatedElement> {
ContainerImpl.Injector create(ContainerImpl var1, M var2, String var3) throws ContainerImpl.MissingDependencyException;
}
}
以上的代碼雖然做了註解,但是我在關於構造方法上的注入器的具體實現還是不太明白,特別是construct(...)方法,暫時放放,總結一下大概是如何實現的:
字段注入器:關鍵的類就是:ContainerImpl.FieldInjector,一個FieldInjector保存的就是一個需要注入(被@inject註解)的字段信息,這裏就是反射應用的最好體現了,一切操作都是在程序運行過程完成的。inject()方法完成了對了字段的注入操作。
//字段注入器
static class FieldInjector implements ContainerImpl.Injector {
//保存了該字段
final Field field;
//字段工廠
final InternalFactory<?> factory;
final ExternalContext<?> externalContext;
public FieldInjector(ContainerImpl container, Field field, String name) throws ContainerImpl.MissingDependencyException {
this.field = field;
//修改可見性
if (!field.isAccessible()) {
SecurityManager sm = System.getSecurityManager();
try {
if (sm != null) {
sm.checkPermission(new ReflectPermission("suppressAccessChecks"));
}
field.setAccessible(true);
} catch (AccessControlException var6) {
throw new DependencyException("Security manager in use, could not access field: " + field.getDeclaringClass().getName() + "(" + field.getName() + ")", var6);
}
}
//保存信息
Key<?> key = Key.newInstance(field.getType(), name);
this.factory = container.getFactory(key);
if (this.factory == null) {
throw new ContainerImpl.MissingDependencyException("No mapping found for dependency " + key + " in " + field + ".");
} else {
this.externalContext = ExternalContext.newInstance(field, key, container);
}
}
//字段注入可能比較好理解
public void inject(InternalContext context, Object o) {
ExternalContext<?> previous = context.getExternalContext();
context.setExternalContext(this.externalContext);
//將對象注入給field的
try {
this.field.set(o, this.factory.create(context));
} catch (IllegalAccessException var8) {
throw new AssertionError(var8);
} finally {
context.setExternalContext(previous);
}
}
}
方法注入器,關注到的ContainerImpl.MethodInjector,一個MethodInjector保存一個方法以及方法上需要注入的參數(參數注入器)。主要的inject()方法調用對象o的method,並將參數注入,其中getParameters()是獲得需要注入的參數的值。
//方法注入器
static class MethodInjector implements ContainerImpl.Injector {
//保存了該方法
final Method method;
//方法的參數,主要是要注入參數
final ContainerImpl.ParameterInjector<?>[] parameterInjectors;
public MethodInjector(ContainerImpl container, Method method, String name) throws ContainerImpl.MissingDependencyException {
this.method = method;
if (!method.isAccessible()) {
SecurityManager sm = System.getSecurityManager();
try {
if (sm != null) {
sm.checkPermission(new ReflectPermission("suppressAccessChecks"));
}
method.setAccessible(true);
} catch (AccessControlException var6) {
throw new DependencyException("Security manager in use, could not access method: " + name + "(" + method.getName() + ")", var6);
}
}
//獲得方法參數
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 0) {
throw new DependencyException(method + " has no parameters to inject.");
} else {
//獲得方法參數的注入器
this.parameterInjectors = container.getParametersInjectors(method, method.getParameterAnnotations(), parameterTypes, name);
}
}
public void inject(InternalContext context, Object o) {
try {
//調用對象o的method,並將參數注入,所以getParameters獲得需要注入的參數的實例
//相當於o.method(ContainerImpl.getParameters(this.method, context, this.parameterInjectors))
this.method.invoke(o, ContainerImpl.getParameters(this.method, context, this.parameterInjectors));
} catch (Exception var4) {
throw new RuntimeException(var4);
}
}
}
參數注入器:保存的參數的信息。注意到的是這個ParameterInjector並沒有實現Injector接口,它的inject()方法發生在:
private static Object[] getParameters(Member member, InternalContext context, ContainerImpl.ParameterInjector[] parameterInjectors) {
if (parameterInjectors == null) {
return null;
} else {
Object[] parameters = new Object[parameterInjectors.length];
//獲得需要注入的參數的實例,依次調用了ParameterInjector類的inject方法,注意到它並沒實現Injector接口
for(int i = 0; i < parameters.length; ++i) {
parameters[i] = parameterInjectors[i].inject(member, context);
}
return parameters;
}
}
而getParameters()方法發生在方法注入器的inject()和構造器注入器的construct()中,傳入的member分別是method(Method)和construct(Construct)。所以總結下來inject()返回了注入參數的實例。
//參數注入器
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;
}
//方法參數的注入,實際上是獲得需要注入的參數的實例
T inject(Member member, InternalContext context) {
//獲得外部上下文的操作
ExternalContext<?> previous = context.getExternalContext();
context.setExternalContext(this.externalContext);
Object var4;
try {
//生成注入參數的實例
var4 = this.factory.create(context);
} finally {
context.setExternalContext(previous);
}
return var4;
}
}
構造器注入器:這個ConstructorInjector也沒有實現Injector接口。主要的方法就是 findConstructorIn(...)找到帶@inject註解的構造器,constructorParameterInjector(...)返回需要注入參數的參數注入器。關於construct(...)我們需要從它的作用地方推測一下:
<T> T inject(Class<T> implementation, InternalContext context) {
try {
ContainerImpl.ConstructorInjector<T> constructor = this.getConstructor(implementation);
return implementation.cast(constructor.construct(context, implementation));
} catch (Exception var4) {
throw new RuntimeException(var4);
}
}
前面代碼我們提到的這個方法的作用(見註釋),我們先看一下第一句:getConstruct(implementation)
<T> ContainerImpl.ConstructorInjector<T> getConstructor(Class<T> implementation) {
return (ContainerImpl.ConstructorInjector)this.constructors.get(implementation);
}
Map<Class<?>, ContainerImpl.ConstructorInjector> constructors = new ReferenceCache<Class<?>, ContainerImpl.ConstructorInjector>() {
protected ContainerImpl.ConstructorInjector<?> create(Class<?> implementation) {
return new ContainerImpl.ConstructorInjector(ContainerImpl.this, implementation);
}
};
這裏會涉及到關於ReferenceCache和它的父類ReferenceMap的相關知識,我們在只說明一下get操作的結果:當獲取不到相應的注入器時,就會帶到了create()方法,於是調用到了ConstructorInjector的構造器。那麼類似於方法構造器,這裏就會生成完整的一個構造注入器。
注意:下面語句也是同樣的道理。
//內部實現的具體方法
void inject(Object o, InternalContext context) {
...
List<ContainerImpl.Injector> injectors = (List)this.injectors.get(o.getClass());
...
}
return implementation.cast(constructor.construct(context, implementation));
這一句應該就是完成對象的創建和依賴部分的注入了。
//構造方法注入器
static class ConstructorInjector<T> {
//class
final Class<T> implementation;
final List<ContainerImpl.Injector> injectors;
//構造方法
final Constructor<T> constructor;
//參數注入器
final ContainerImpl.ParameterInjector<?>[] parameterInjectors;
//
ConstructorInjector(ContainerImpl container, Class<T> implementation) {
this.implementation = implementation;
//找到帶@inject註解的構造器
this.constructor = this.findConstructorIn(implementation);
//修改可達性
if (!this.constructor.isAccessible()) {
SecurityManager sm = System.getSecurityManager();
try {
if (sm != null) {
sm.checkPermission(new ReflectPermission("suppressAccessChecks"));
}
this.constructor.setAccessible(true);
} catch (AccessControlException var8) {
throw new DependencyException("Security manager in use, could not access constructor: " + implementation.getName() + "(" + this.constructor.getName() + ")", var8);
}
}
ContainerImpl.MissingDependencyException exception = null;
Inject inject = null;
ContainerImpl.ParameterInjector[] parameters = null;
try {
//獲取需要注入的參數
inject = (Inject)this.constructor.getAnnotation(Inject.class);
parameters = this.constructParameterInjector(inject, container, this.constructor);
} catch (ContainerImpl.MissingDependencyException var7) {
exception = var7;
}
this.parameterInjectors = parameters;
if (exception != null && inject != null && inject.required()) {
throw new DependencyException(exception);
} else {
this.injectors = (List)container.injectors.get(implementation);
}
}
//找到@inject的參數
ContainerImpl.ParameterInjector<?>[] constructParameterInjector(Inject inject, ContainerImpl container, Constructor<T> constructor) throws ContainerImpl.MissingDependencyException {
return constructor.getParameterTypes().length == 0 ? null : container.getParametersInjectors(constructor, constructor.getParameterAnnotations(), constructor.getParameterTypes(), inject.value());
}
//找到帶註解@inject的構造器
private Constructor<T> findConstructorIn(Class<T> implementation) {
Constructor<T> found = null;
Constructor<T>[] declaredConstructors = (Constructor[])implementation.getDeclaredConstructors();
Constructor[] arr$ = declaredConstructors;
int len$ = declaredConstructors.length;
for(int i$ = 0; i$ < len$; ++i$) {
Constructor<T> constructor = arr$[i$];
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;
} else {
try {
return implementation.getDeclaredConstructor();
} catch (NoSuchMethodException var8) {
throw new DependencyException("Could not find a suitable constructor in " + implementation.getName() + ".");
}
}
}
Object construct(InternalContext context, Class<? super T> expectedType) {
ConstructionContext<T> constructionContext = context.getConstructionContext(this);
if (constructionContext.isConstructing()) {
return constructionContext.createProxy(expectedType);
} else {
T t = constructionContext.getCurrentReference();
if (t != null) {
return t;
} else {
try {
constructionContext.startConstruction();
try {
Object[] parameters = ContainerImpl.getParameters(this.constructor, context, this.parameterInjectors);
//構造對象
t = this.constructor.newInstance(parameters);
constructionContext.setProxyDelegates(t);
} finally {
constructionContext.finishConstruction();
}
constructionContext.setCurrentReference(t);
Iterator i$ = this.injectors.iterator();
//完成依賴部分的注入
while(i$.hasNext()) {
ContainerImpl.Injector injector = (ContainerImpl.Injector)i$.next();
injector.inject(context, t);
}
Object var18 = t;
return var18;
} catch (IllegalAccessException | InvocationTargetException | InstantiationException var15) {
throw new RuntimeException(var15);
} finally {
constructionContext.removeCurrentReference();
}
}
}
}
}
對象注入的實例
//發生在DefaultConfiguration.reloadContainer()
//假設注入的對象是StrutsXmlConfigurationProvider
this.container.inject(containerProvider);
我們直接跳到起作用的方法中:
//其中o就是StrutsXmlConfigurationProvider
//暫時忽略context
void inject(Object o, InternalContext context) {
//這裏會獲得StrutsXmlConfigurationProvider中的注入器,也就是需要注入的地方,查看父類我們會發現兩個方法如下
List<ContainerImpl.Injector> injectors = (List)this.injectors.get(o.getClass());
Iterator i$ = injectors.iterator();
while(i$.hasNext()) {
//依次注入,這兩個是方法上的注入器
ContainerImpl.Injector injector = (ContainerImpl.Injector)i$.next();
injector.inject(context, o);
}
}
XmlConfigurationProvider
@Inject
public void setObjectFactory(ObjectFactory objectFactory) {
this.objectFactory = objectFactory;
}
@Inject
public void setFileManagerFactory(FileManagerFactory fileManagerFactory) {
this.fileManager = fileManagerFactory.getFileManager();
}
那麼接下來應該會依次調用兩個方法的注入器:injector.inject(context,o)
MethodInjector.inject
public void inject(InternalContext context, Object o) {
try {
//調用兩個方法
this.method.invoke(o, ContainerImpl.getParameters(this.method, context, this.parameterInjectors));
} catch (Exception var4) {
throw new RuntimeException(var4);
}
}
這裏就相當於,getParameters()就是獲得實例對象
o.setObjectFactory(ContainerImpl.getParameters(this.method, context, this.parameterInjectors))
那麼接下來的就不多贅述了,我們可以直接看ParamtersInjector.inject(),它會去create一個實例以供注入。
T inject(Member member, InternalContext context) {
ExternalContext<?> previous = context.getExternalContext();
context.setExternalContext(this.externalContext);
Object var4;
try {
//生成實例
var4 = this.factory.create(context);
} finally {
context.setExternalContext(previous);
}
return var4;
}
獲取對象實例
這個似乎沒有什麼需要細說的地方,主要步驟就是通過type和name獲取內部工廠,然後生成對象。涉及到factories可以參考factories。
<T> InternalFactory<? extends T> getFactory(Key<T> key) {
return (InternalFactory)this.factories.get(key);
}
<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((Member)null, key, this));
Object var7;
try {
InternalFactory o = this.getFactory(key);
if (o != null) {
var7 = this.getFactory(key).create(context);
return var7;
}
var7 = null;
} finally {
context.setExternalContext(previous);
}
return var7;
}
<T> T getInstance(Class<T> type, InternalContext context) {
return this.getInstance(type, "default", context);
}
關於Container的內容就暫時到這吧。還有存在很多不足的地方,希望慢慢也能快點理解改正。
下一篇:Dispatcher(2)