SharedSecrets机制如何工作?

时间:2017-10-13 04:16:45

标签: java

select b.PatientId,b.ResponsibleProvider,c.ProviderCount,c.MaxApptdate from ResponsibleProvider b outer apply (SELECT a.PatientId, a.Provider, COUNT(a.Provider) ProviderCount, MAX(a.Apptdate) MaxApptdate FROM Appointments a WHERE a.Apptdate BETWEEN DATEADD(YY, -1, GETDATE()) AND GETDATE() AND a.FacilityId LIKE 2 and b.PatientId = a.PatientId and b.ResponsibleProvider = a.Provider GROUP BY a.PatientId, a.Provider )c 将自己描述为:

  

“共享秘密”的存储库,它是一种机制       在没有的情况下在另一个包中调用implementation-private方法       使用反射。包私有类实现公共       接口并提供调用package-private方法的能力       在那个包内;实现该接口的对象是       通过限制访问的第三个包提供。       该框架避免了使用反射的主要缺点       为此目的,即丢失编译时检查。

有人可以提供一个示例来演示这种机制如何使一个包中的类能够访问另一个包中的包私有方法吗?

1 个答案:

答案 0 :(得分:3)

引用http://blog.fuseyism.com/index.php/2008/05/26/sharing-secrets/

  

通过OpenJDK查看VM项目时,我注意到他们有一个相当有趣的解决方案。这封装在sun.misc.SharedSecrets中。此类提供对许多公共接口的实例的访问,例如sun.misc.JavaLangAccess。实际的实现在适当的包中作为内部类提供,例如java.lang,它可以访问./ / p>中的private和package-private变量和方法

这是一个具体的例子:

  • 我们有两个类:CharacterStory
  • 我们希望Story能够在Character上调用私有方法,而不是其他人。

<强> Main.java:

package external.main;

import external.character.Character;
import external.story.Story;

public class Main
{
    public static void main(String[] args)
    {
        Story story = new Story();
        story.introduce(Character.HARRY_POTTER);
        story.introduce(Character.RON_WEASLEY);
        story.introduce(Character.HERMIONE_GRANGER);
    }
}

<强> Story.java

package external.story;

import external.character.Character;
import internal.secrets.SharedSecrets;

public final class Story
{
    /**
     * Introduces a character.
     *
     * @param character the character
     */
    public void introduce(Character character)
    {
        System.out.println(character.name() + " enters the room and says: " + SharedSecrets.INSTANCE.secretCharacter.getPhrase(character));
    }
}

<强> Character.java:

package external.character;

import internal.secrets.SecretCharacter;
import internal.secrets.SharedSecrets;

public enum Character
{
    HARRY_POTTER
    {
        @Override
        String getPhrase()
        {
            return "Your bird, there was nothing I could do. He just caught fire.";
        }
    },
    RON_WEASLEY
    {
        @Override
        String getPhrase()
        {
            return "Who are you and what have you done with Hermione Granger?";
        }
    },
    HERMIONE_GRANGER
    {
        @Override
        String getPhrase()
        {
            return "I'm not an owl!";
        }
    };

    static
    {
        SharedSecrets.INSTANCE.secretCharacter = new SecretCharacter()
        {
            @Override
            public String getPhrase(Character character)
            {
                return character.getPhrase();
            }
        };
    }

    /**
     * @return the character's introductory phrase
     */
    abstract String getPhrase();
}

<强> SharedSecrets.java:

package internal.secrets;

public final class SharedSecrets
{
    public static SharedSecrets INSTANCE = new SharedSecrets();
    public SecretCharacter secretCharacter;

    /**
     * Prevent construction.
     */
    private SharedSecrets()
    {
    }
}

<强> SecretCharacter.java:

package internal.secrets;

import external.character.Character;

public interface SecretCharacter
{
    /**
     * @param character a character
     * @return the character's introductory phrase
     */
    String getPhrase(Character character);
}

<强> module-info.java:

module SharedSecret
{
    exports external.character;
    exports external.main;
    exports external.story;
}

<强>输出

  

HARRY_POTTER进入房间说:你的鸟,我无能为力。他刚起火了。

     

RON_WEASLEY走进房间说:你是谁,你和Hermione Granger做了什么?

     

HERMIONE_GRANGER走进房间说:我不是猫头鹰!

<强>解释

  • external.character.Character.getPhrase()受包保护。
  • external.story.Story位于不同的包中。
  • 通常Story无法调用Character.getPhrase();但是,SharedSecrets允许Character与其信任的类共享访问权限。
  • Story调用SharedSecrets.INSTANCE.secretCharacter,它使用匿名嵌套类来访问Character内部。
  • external.story.Story可以访问internal.secrets.SharedSecrets,因为这两个位于同一模块中,但外部用户无法访问它,因为module-info.java不会导出该包。