(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)