6

プロジェクトでSpringとgraphql -java(graphql-java-annotation)を使用しています。データ部分を取得するために、DataFetcher を使用してサービスから (データベースから) データを取得しています。

奇妙なことに、myService常にnullです。理由を知っている人はいますか?

DataFetcher

@Component
public class MyDataFetcher implements DataFetcher {

    // get data from database
    @Autowired
    private MyService myService;

    @Override
    public Object get(DataFetchingEnvironment environment) {
        return myService.getData();
    }
}

スキーマ

@Component
@GraphQLName("Query")
public class MyGraphSchema {

    @GraphQLField
    @GraphQLDataFetcher(MyDataFetcher.class)
    public Data getData() {
        return null;
    }
}

マイサービス

@Service
public class MyService {

    @Autowired
    private MyRepository myRepo;

    @Transactional(readOnly = true)
    public Data getData() {
        return myRepo.getData();
    }
}

本試験

@Bean
public String testGraphql(){
    GraphQLObjectType object = GraphQLAnnotations.object(MyGraphSchema.class);
    GraphQLSchema schema = newSchema().query(object).build();
    GraphQL graphql = new GraphQL(schema);

    ExecutionResult result = graphql.execute("{getData {id name desc}}");;
    Map<String, Object> v = (Map<String, Object>) result.getData();
    System.out.println(v);
    return v.toString();
}
4

3 に答える 3

6

graphql-java-annotation では、データ フェッチャーはアノテーションによって定義されるため、フレームワークによって (リフレクションを使用してコンストラクターを取得する) 構築されるため、Bean にすることはできません。

これに対して私が見つけた回避策は、それを として設定することApplicationContextAwareであり、その後、Bean の代わりにいくつかの静的フィールドを初期化できます。最も素晴らしいことではありませんが、機能します:

@Component
public class MyDataFetcher implements DataFetcher, ApplicationContextAware {

    private static MyService myService;
    private static ApplicationContext context;

    @Override
    public Object get(DataFetchingEnvironment environment) {
        return myService.getData();
    }

    @override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansExcepion {
        context = applicationContext;
        myService = context.getBean(MyService.class);
    }
}

基本的に、graphQL によって初期化されたデータ フェッチャーの新しいインスタンスを引き続き取得しますが、Spring もそれを初期化し、myService静的であるため、初期化されたインスタンスを取得します。

于 2017-01-03T09:28:35.710 に答える
1

@Nir Levy が提供するソリューションは完全に機能します。ここでもう少し再利用可能にするためです。Bean ルックアップ ロジックをカプセル化する抽象クラスを抽出し、そのサブクラスに対してオートワイヤリングを機能させることができます。

public abstract class SpringContextAwareDataFetcher implements DataFetcher, ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public final Object get(DataFetchingEnvironment environment) {
        return applicationContext.getBean(this.getClass()).fetch(environment);
    }

    protected abstract Object fetch(DataFetchingEnvironment environment);
}

サブクラスは次のようになります。

@Component
public class UserDataFetcher extends SpringContextAwareDataFetcher {

    @Autowired
    private UserService userService;

    @Override
    public String fetch(DataFetchingEnvironment environment) {
        User user = (User) environment.getSource();
        return userService.getUser(user.getId()).getName();
    }
}
于 2017-01-24T01:58:34.500 に答える