3

我想知道是否有人有一种模式可以帮助我实现以下目标:

我们有一个名为 Employee 的 JPA 实体,上面有一个 setLineManager 方法。我们还有一个单独的 updateLineStructureService,它是一个 Spring 管理的服务 bean。我们想尝试确保这个 setLineManager 方法只能从 updateLineStructureService 调用,而不能直接从任何其他类调用。

有没有办法允许服务访问此方法而不将其暴露给任何其他类?我知道我可以授予方法包级别的访问权限并将服务放在与 Employee 相同的包中,但这不适合我们的包结构,所以我不希望这样做。我也知道我可以将方法设为私有,并通过在这个地方的反射来访问它,但我根本不喜欢这种解决方案。

有任何想法吗?

4

6 回答 6

1

您可以检查堆栈跟踪(使用Throwable#getStackTrace())并查看它是否在指定位置包含允许的方法。

于 2012-06-04T17:04:20.213 回答
1

使用仅可用于其他服务类的内部类:

public class Employee
{
  static {
    LineStructureService.registerEmployeeHelper(new EmployeeHelper() {
      @Override
      public void setLineManager(Employee emp, Object foo) {
        emp.setLineManager(foo);
      }
    });
  }

  public static void init() {}

  private void setLineManager(Object foo) { }  
}

public class LineStructureService
{
  private static volatile EmployeeHelper _helper;

  static {
    // ensure that Employee class is loaded and helper registered
    Employee.init();
  }

  public static synchronized void registerEmployeeHelper(EmployeeHelper helper) {
    _helper = helper;
  }

  public void doSomething(Employee emp)
  {
    // now this class can call setLineManager on Employee
    _helper.setLineManager(emp, blah);
  }

  public interface EmployeeHelper {
    public void setLineManager(Employee emp, Object foo);
  }
}
于 2012-06-04T17:51:11.693 回答
1

在下面的代码片段中,System.PrivateEmployee在 System 类之外是不可见的。因此实际上privateMethod是私有的,只能从System类中调用。由于System.PrivateEmployeeextendsSystem.PublicEmployee它可以在System类外使用System.PublicEmployee

public class System
{
      public static interface PublicEmployee { void publicMethod ( ) ; }
      private static interface PrivateEmployee extends PublicEmployee { void privateMethod ( ) ; }
}
于 2012-06-04T17:48:31.737 回答
0

您可以使用 AOP(例如 AspectJ 或 CDI)来拦截对 setLineManager() 的调用;如果调用者是 updateLineStructureService() 调用该方法;如果不是什么也不做,或者引发异常或其他什么。

于 2012-06-04T17:52:56.110 回答
0

一个类可以访问其他类的私有方法的唯一方法是使用内部类。如果这不是一个选项,则无法做到这一点。

于 2012-06-04T17:04:36.517 回答
0

一种方法是制作两种形式的Employee。

"BasicEmployee" 具有除 setLineManager() 之外的所有方法。“ExtendedEmployee”扩展了 BasicEmployee 并添加了一个public void setLineManager(). (我假设这些是类,但它们也可以是接口)在底层,一切都是真正的 FullEmployee(为了清楚起见,您可以将 BasicEmployee 设为抽象)。但是,在代码中,在除 UpdateLineStructureService 之外的所有类中,您将其声明为 BasicEmployee。只有在 UpdateLineStructureService 中才将其声明为 FullEmployee。因此,只有 UpdateLineStructureService 可以轻松访问 setLineManager()

现在,流氓编码员总是可以将他们的 BasicEmployee 转换为 ExtendedEmployee 以访问 setLineManager(),因此这并不完全安全。但这是限制访问的合理模式。

于 2012-06-04T17:32:47.070 回答