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方法的實現

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章