洞察探索如何利用兼容微信生态的小程序容器,实现跨平台开发,助力金融和车联网行业的数字化转型。
600
2022-11-26
XWork容器的存储结构
我们可以看到,在Container的默认实现,ContainerImpl中有两个实例变量。factoris和factoryNamesByType。
对象制造工厂
class ContainerImpl implements Container { final Map
首先我们看factories,它的值是由构造函数传递进来的。我们看看它的类型。
map形式的,key是Key。
class Key
看这个type与name是不是想起什么了?
对,就是struts-default.xml
type和name能唯一确认了一个bean。
再看看InternalFactory
interface InternalFactory
InternalFactory中存储了生成一个类的方法,而不是这个类的实例。
注入器
现在我们再看看注入器。
注入器是干什么的?
还记得上一篇我们说的人和车的例子么?
人只需要告诉容器,自己需要一辆车子,容器就会自动为人注入一辆车。
到底怎么自动的?注入器就是做这个事的。
咱们慢慢看。
ContainerImpl的inject方法如下所示。 //o就是人 人需要一辆车 void inject( Object o, InternalContext context ) { //获得人身上的所有注入器 List
获得"人"上都有哪些注入器。
this.injectors.get(o.getClass());
在下面的例子中,人就有一个"方法注入器"
public class Person{ private Car car; public Person(){ //其他代码 } @Inject() public void setCar(Car c){ this.car=c; } public void drive(){ car.drive(); }}
注入器分两类,方法注入器,属性注入器。
其接口如下。
/** * Injects a field or method in a given object. */ interface Injector extends Serializable { void inject( InternalContext context, Object o ); }
我们看看属性注入器,方法注入器类似。
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; ... } Key> key = Key.newInstance(field.getType(), name); factory = container.getFactory(key); //标识2 ... public void inject( InternalContext context, Object o ) { ExternalContext> previous = context.getExternalContext(); context.setExternalContext(externalContext); //省略trycatch field.set(o, factory.create(context));//标识1 }}
标识2 就是从容器里获得这个key的InternalFactory
在上面代码的标识1出,注入器做了最后的工作就是注入。
相信大家对InternalFactory的creat方法很好奇,到底是怎么实现的。
咱们不妨换个思路,field.set()的签名如下
public void set(Object obj, Object value) throws IllegalArgumentException, IllegalAccessException
如果对person p的字段Car c,及容器内部的Car c2来说,
它的调用就是
c.set(p,c2);
也就是说InternalFactory的creat就是产生了容器内的所托管的对象而已。
我们再看看ContainerImpl里injectors这个参数。
final Map
怎么回事,看着好复杂呀。
public abstract class ReferenceCache
ReferenceMap实现了map接口。
有了ReferenceCatch,我们操作map就高效多了,当我们调用get方法时,如果key已经存在,就直接返回,否则就调用creat产生并缓存,下一次就不用再create了。
同时大家注意这个create是个抽象方法。
再换句话说,ContainerImpl中的injectors是在运行期动态构建的。
那么到底什么呢时候调用上面标识7处的creat方法呢?
在上面代码标识8处get后调用(ctrl+f 标识8)
这里牵扯到struts2的缓存技术,这边就先不讲了。
可参阅拙作
Struts2中的缓存---以Injector为例
反正效果就是,当我们调用get方法时,如果key已经存在,就直接返回,否则就调用creat产生并缓存,下一次就不用再create了
好,接下来我们就看看标识4处的addInjectors方法。
void addInjectors( Class clazz, List
我们看看属性注入器。
void addInjectorsForFields( Field[] fields, boolean statics, List
在addInjectorsForFields里面,只有一行代码,就是调用addInjectorsForMembers,其参数的最后一个类型是InjectorFactory。
如果大家再看看addInjectorsForMethods,只要我们在类的方法或成员变量上加上Inject这annotation,容器就会给参数注入一个相应的实例。
先看到这里吧,下一节我们再看XWork的实现机理。
(分析struts2的源码对我来说,还是很有难度的,文章写得不好,欢迎拍砖,共同进步)
感谢glt
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~