如何在只能从一个其他类访问的Java类中创建方法

时间:2012-06-04 16:57:17

标签: java spring

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

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

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

有什么想法吗?

6 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

在以下代码段中,System.PrivateEmployee在System类外部不可见。因此,有效privateMethod是私有的,只能在System类中调用。由于System.PrivateEmployee扩展System.PublicEmployee,因此可以在System类之外使用System.PublicEmployee

public class System
{
      public static interface PublicEmployee { void publicMethod ( ) ; }
      private static interface PrivateEmployee extends PublicEmployee { void privateMethod ( ) ; }
}

答案 2 :(得分: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);
  }
}

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

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

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

答案 5 :(得分:0)

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