当前位置: 首页 > 知识库问答 >
问题:

将bean注入GraphQL的DataFetcher

谢承颜
2023-03-14

我在用Spring

奇怪的是:myService总是空的。有人知道原因吗?

数据提取程序

@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();
}

共有3个答案

元景天
2023-03-14

@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();
    }
}
东方河
2023-03-14
匿名用户

尽管@Nir的方法有效(我经常在JPA事件侦听器中使用它),但DataFetcher对象是单例,因此通过静态属性注入有点麻烦。

但是,GraphQL的执行方法允许您将对象作为上下文传入,然后该上下文将在DataFetching环境DataFetcher内的对象中可用(参见下面的graphql.execute()行):

@Component
public class GraphQLService {

    @Autowired
    MyService myService;

    public Object getGraphQLResult() {
        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}}", myService);

        return result.getData();
    }
}

public class MyDataFetcher implements DataFetcher {

    @Override
    public Object get(DataFetchingEnvironment environment) {
        MyService myService = (MyService) environment.getContext();

        return myService.getData();
    }
}

卜阳
2023-03-14

由于在graph ql-java-anotation中,数据获取器是由注释定义的,它是由框架构造的(使用反射来获取构造函数),因此它不能是bean。

我为此找到的解决方法是将其设置为Application ationContextAware,然后我可以初始化一些静态字段而不是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是静态的,所以您将获得初始化的实例。

 类似资料:
  • 我有一个JSF的问题,CDI项目。我做了大量研究,发现在CDI中没有注释。我用对话框解决基于ajax的页面的问题。我想将变量从DataTable传递到dialog。为此,我不能使用bean,因为在请求结束后会丢弃值。有人能帮我解决吗?我不能使用,但这是一个糟糕的做法。或者只保存这一个变量到会话谁知道。你们能给我一些提示如何优雅地解决这个问题吗? 以下是错误消息:

  • 问题内容: 是否可以将Spring bean注入RestEasy @Path类中?我设法通过Jersey并使用@InjectParam注释完成了此操作,但是由于某些其他原因,我需要切换到RestEasy,而且我似乎找不到解决方法(尝试了javax.inject.Inject,但没有)。 编辑 此解决方案有效:http : //www.mkyong.com/webservices/jax-rs/re

  • 我正在开发一个遗留的JSF应用程序,我们正在慢慢地将其移植到Spring MVC。我们正在使用Spring Security来控制登录信息。在用户登录之后,JSF页面全局地实例化一个在任何地方都使用的会话作用域bean。我想更改应用程序,这样我们就可以先进入用Spring MVC开发的页面。 我尝试的一种方法是将bean转换为spring bean,并将其注入JSF,但不幸的是,这需要对bean进

  • 我刚接触Spring,正在尝试理解“将一个原型bean注入一个单例bean”的概念。根据我在singleton中的理解,每个Spring IoC容器只有一个实例,不管您检索它多少次。,因为仍未实例化。我开发了以下示例,其中在单个bean中给出了原型bean的参考,如下所示: RequestProcessor.java requestValidator.java 如何解决?我的理解正确吗? 另一种方

  • 问题内容: 我试图将EJB注入到Spring(3.1.2)服务中(都在不同的 WAR中)两者都非常简单(删除了方法以简化示例): EJB: Service: 事情很简单,但我尝试过: 它没有用。然后我还尝试了: and 但都没有奏效。 我设法使用以下方法注入了EJB: 在我的spring配置和服务中: 但我真的不喜欢这种解决方案。我希望在某些注释中包含我的JNDI路径,例如: 问题答案: 我们找到

  • 我们有一个带有@EJB字段的Spring托管bean 在我们的spring xml中 这在WebLogic和Glassfish中有效,但在JBoss 7.1.2中无效(请参阅stacktrac@[1])。 仔细研究Spring代码,似乎它将JNDI名称(即“MyService”)转换为Java EE标准容器前缀“Java:comp/env/”[2],JBoss似乎不支持这个前缀。从JBoss日志来