0

在工作中有一個流程框架。它使用鍵和容器來設置參數,而不使用專用的構造函數(它基本上是類型安全的異構容器模式)。訪問級別感知依賴注入到繼承字段

我最近添加了依賴注入。 下面你找到一個代表性的例子(它缺少null檢查,訪問控制等)

private static void inject(Process instance, Container c) throws Exception 
    { 
    Class<?> reference = instance.getClass(); 
    for (Field field : reference.getDeclaredFields()) 
    { 
     Inject inject = field.getAnnotation(Inject.class); 

     Key<Object> key = new Key<>(inject.key()); 
     field.set(instance, c.getObject(key)); 
    } 
    } 

的實施工作,但現在我需要加強它以也注入到繼承的字段。

我沒有問題檢索類型層次和所有註釋,繼承字段。但爲了遵守Java,我絕不能注入到每個檢索的字段中。

只有當領域是:

  1. public
  2. protected
  3. package-privated,並具有相同的封裝reference
  4. private一個類中聲明,並在類包圍reference宣佈,其必須是內部類(非靜態嵌套類)。

項目1 - 3很容易檢查。我對最後一項有困難。有沒有優雅的解決方案?

我想了解如何使用java.lang.Class.isMemberClass()並比較類名。

目前我的支票看起來像這樣

private static boolean accessAllowed(Class<?> reference, Field field) 
    { 
    int modifiers = field.getModifiers(); 

    boolean hasAccess = Modifier.isPublic(modifiers); 
    hasAccess |= Modifier.isProtected(modifiers); 

    // TODO fix 
    hasAccess |= Modifier.isPrivate(modifiers) /* add check as defined in 4. */; 

    // no access and not private means field is package-private 
    if (!hasAccess && !Modifier.isPrivate(modifiers)) 
     hasAccess = reference.getPackage().equals(field.getDeclaringClass().getPackage()); 

    return hasAccess; 
    } 

有一個簡單的和/或有效的方式來找出一個類是否是另一個類封閉?還是有另一種方法來確定我是否被允許注射?

回答

0

以下解決方案應處理私人情況。

派生類是reference,它試圖設置部件從fieldDeclaringClass

static boolean hasPrivateAccessRelation(Class<?> reference, Class<?> fieldDeclaringClass) 
    { 
    boolean isMemberClass = reference.isMemberClass(); 
    boolean isEnclosingClass = reference.getName().contains(fieldDeclaringClass.getName()); 

    // static nested classes can't access private members of enclosing class 
    return isMemberClass && isEnclosingClass && !Modifier.isStatic(reference.getModifiers()); 
    } 

遺傳代碼工作如果派生類是內部類的fieldDeclaringClass。如果它是靜態嵌套類,它將失敗,因爲它們無法訪問封閉類的私有字段。

以前的檢查是必要的,以確保referencefieldDeclaringClass不相等。因爲在這種情況下,static將是一個有效的修飾符,因爲嵌套類總是可以訪問自己的字段。