xwork 中的依赖注入

控制反转
每个对象对于自身逻辑的执行能力,被其所依赖的对象反向控制了,这也就是控制反转的本质含义。

容器由一系列操作接口构成,其中应该只是包含获取对象实例以及管理对象之间的依赖关系这两类操作方法。
容器是一个辅助的编程元素,它在整个系统中应该被实例化为一个全局的、单例的对象。
容器在系统初始化时进行自身的初始化。系统应该提供一个可靠的,在任何编程层次都能对这个全局的容器或者容器中管理的对象进行访问的机制。

Xwork容器所管理的对象包括所有框架配置定义中的“容器配置元素”

调用Xwork容器的inject方法,能够帮助我们将容器所管理的对象注入到任意的对象实例中去,从而建立起任意对象与框架元素沟通的桥梁
@inject注解:设置在任何对象的方法,构造函数,内部实例变量,或者参数变量之中。
容器进行依赖注入的步骤
为某个对象的方法等加入@inject注解。
调用inject方法,完成被加入Annotation的对象的依赖注入。

需要特别注意internalfactory的create方法具体实现是什么,在多处引用,容易混淆
xwork容器的实现?
在这里插入图片描述
内部封转两个实例变量:factories和factoryNamesByType。都是map结构。factoryNameByType键为Class,值是对象的name(key中的name的集合)。可以用于查找某个类在容器中的所有对象。
在这里插入图片描述
InternalFactory泛型接口,用于指定对象的创建机制。Key类记录type,name,hashcode。(即bean用于寻址的type和name)。
factories类键为Key,值为InternalFactory。键记录对象的信息,值记录对象创建机制。
所以容器内部缓存的是对象实例的构建方法,并不是对象实例。

缓存对象与对象之间关系的被称为注入器
在这里插入图片描述
injectors键是一个class对象,值是所有属于Class的注入器的一个list集合。
ReferenceCache是Xwork框架对于缓存的一种简单实现。简单而言,在调用get方法获取其值时,会先查询是否已存在相应对象,否则调用create方法创建对象。 内部维护着一个concurrentMap的引用,并且应用了THreadLocal模式规避了多线程安全问题。

void addInjectors(Class clazz, List<ContainerImpl.Injector> injectors) {
        if (clazz != Object.class) {
        //递归调用自身,以完成对父类注入器的查找
            this.addInjectors(clazz.getSuperclass(), injectors);
         //针对所有属性查找满足条件的注入器,并加入到injectors
            this.addInjectorsForFields(clazz.getDeclaredFields(), false, injectors);
        //针对所有方法查找满足条件的注入器,并加入到injectors
            this.addInjectorsForMethods(clazz.getDeclaredMethods(), false, injectors);
        }
    }
void addInjectorsForMethods(Method[] methods, boolean statics, List<ContainerImpl.Injector> injectors) {
//使用统一的接口addInjectorsForMembers进行查找,并在使用匿名类实现injectFactory接口重新create方法,指定相应的injector的实际实现类
        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);
            }
        });
    }
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);
            }
        });
    }
    //统一injector的查找方式
<M extends Member & AnnotatedElement> void addInjectorsForMembers(
            List<M> members, boolean statics, List<Injector> injectors, InjectorFactory<M> injectorFactory) {
        for (M member : members) {
            if (isStatic(member) == statics) {
            //查找当前传入的member是否具备inject的Annotation
                Inject inject = member.getAnnotation(Inject.class);
                if (inject != null) {
                    try {
                    //调用传入的injectorfactory中的create方法创建真正的injector实例。inject.value()用于初始化inject的name属性,即注解内容添加到injector中
                        injectors.add(injectorFactory.create(this, member, inject.value()));
                    } catch (MissingDependencyException e) {
                        if (inject.required()) {
                            throw new DependencyException(e);
                        }
                    }
                }
            }
        }
    }

addInjectors用于injectors的值对象injectorFactory的构建,其中用匿名类的方式实现了InternalFactory的抽象方法create。injectors.add(injectorFactory.create(this, member, inject.value()));
在这里向inject传递了inject注解的内容。即被注入的对象name

//获取实例
<T> T getInstance(Class<T> type, InternalContext context) {
        return this.getInstance(type, "default", context);
    }
 <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 {
        //通过key类寻找InternalFactory。Internalfactory是一个接口,具体实现采用匿名类,在addinjectors时注入
            InternalFactory o = this.getFactory(key);
            if (o == null) {
                var7 = null;
                return var7;
            }
//调用InternalFactory的create方法,对于这个create方式不是用的injectors的create,而是使用的factories中的internalfactory。
            var7 = this.getFactory(key).create(context);
        } finally {
            context.setExternalContext(previous);
        }

        return var7;
    }

依赖注入

//属性注入器
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);
                }
            }
//根据type和name在内部工厂中找到对应的对象构造工厂,如果没有工厂则注入失败。
            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 {
            //为对象的构建设置externalContext
                this.externalContext = ExternalContext.newInstance(field, key, container);
            }
        }
//实际实施依赖注入的方法。
        public void inject(InternalContext context, Object o) {
            ExternalContext<?> previous = context.getExternalContext();
            context.setExternalContext(this.externalContext);
//使用初始化时找到的对象工厂创建对象,并使用反射注入。
//注意:factory是在factories中找到的internalfactory,而不是injectors中找到的,所以两者的create方法有不同。需要着重注意区别。
            try {
                this.field.set(o, this.factory.create(context));
            } catch (IllegalAccessException var8) {
                throw new AssertionError(var8);
            } finally {
                context.setExternalContext(previous);
            }

        }
    }

//方法注入器
static class MethodInjector implements ContainerImpl.Injector {
        final Method method;
        final ContainerImpl.ParameterInjector<?>[] parameterInjectors;

        public MethodInjector(ContainerImpl container, Method method, String name) throws ContainerImpl.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 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 {
            //针对每个参数查找对应的injector
                this.parameterInjectors = container.getParametersInjectors(method, method.getParameterAnnotations(), parameterTypes, name);
            }
        }
//实施依赖注入
        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);
            }
        }
    }
//容器中的inject方法
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) {
//在传入的对象中查找需要被实施依赖注入的字段或者方法
        List<ContainerImpl.Injector> injectors = (List)this.injectors.get(o.getClass());
        Iterator i$ = injectors.iterator();

        while(i$.hasNext()) {
        //调用不同的injectory的实现了实施依赖注入
            ContainerImpl.Injector injector = (ContainerImpl.Injector)i$.next();
            injector.inject(context, o);
        }
    }

在深入查看依赖注入即this.factory.create(context)(filedinjector中)方法,是在container容器初始化时做的实现,具体而言与scope,containerbuilder有关,模板方法的应用导致很难找到具体实现,需要通过断点一步步查看容器创建过程才能够知道具体的create方法的实现

发布了79 篇原创文章 · 获赞 0 · 访问量 2656

猜你喜欢

转载自blog.csdn.net/qq_41017546/article/details/105056862