public static <FnT extends DoFn<?, ?>> DoFnSignature getSignature(Class<FnT> fn) {
    return signatureCache.computeIfAbsent(fn, DoFnSignatures::parseSignature);
  }
@Test
  public void testFieldAccess() throws IllegalAccessException {
    FieldAccessDescriptor descriptor = FieldAccessDescriptor.withFieldNames("foo", "bar");
    DoFn<String, String> doFn =
        new DoFn<String, String>() {
          @FieldAccess("foo")
          final FieldAccessDescriptor fieldAccess = descriptor;

          @ProcessElement
          public void process(@FieldAccess("foo") @Element Row row) {}
        };

    DoFnSignature sig = DoFnSignatures.getSignature(doFn.getClass());
    assertThat(sig.fieldAccessDeclarations().get("foo"), notNullValue());
    Field field = sig.fieldAccessDeclarations().get("foo").field();
    assertThat(field.getName(), equalTo("fieldAccess"));
    assertThat(field.get(doFn), equalTo(descriptor));

    assertFalse(sig.processElement().getSchemaElementParameters().isEmpty());
  }