Java Jersey 2.x中的依赖注入

Java Jersey 2.x中的依赖注入,java,rest,dependency-injection,jersey,hk2,Java,Rest,Dependency Injection,Jersey,Hk2,我定义了一个AbstractBinder并将其注册到我的JAX-RS应用程序中。绑定器指定依赖项注入应该如何创建我的类 public class AppBinder extends AbstractBinder { @Override protected void configure() { bind(TranslationImportServiceImpl.class).to(TranslationImportService.class); bindAsContract(Im

我定义了一个AbstractBinder并将其注册到我的JAX-RS应用程序中。绑定器指定依赖项注入应该如何创建我的类

public class AppBinder extends AbstractBinder {
@Override
protected void configure() {
     bind(TranslationImportServiceImpl.class).to(TranslationImportService.class);
    bindAsContract(ImportCandidateBuilder.class);
    bind(DomainsBusinessServices.class)
            .to(IDomainsBusinessServices.class).in(Singleton.class);
    bind(CodeBusinessService.class)
            .to(ICodeBusinessService.class).in(Singleton.class);
    bind(LangBusinessService.class)
            .to(ILangBusinessService.class).in(Singleton.class);
    bind(TranslationBusinessService.class)
            .to(ITranslationBusinessService.class).in(Singleton.class);
    bind(SessionImpl.class)
            .to(Session.class).in(Singleton.class);
    bind(SessionFactoryImpl.class)
            .to(SessionFactory.class).in(Singleton.class);
    bind(CriteriaImpl.class)
            .to(Criteria.class).in(Singleton.class);
    bindAsContract(DefaultBusinessService.class);
}
我实现了web.xml的init参数中指定的应用程序类

public class Application extends ResourceConfig {
public Application() {
    register(new AppBinder());
    packages(true, "web.rest");
}
web.xml

<servlet>
    <servlet-name>Jersey Web Application</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>web.rest</param-value>
    </init-param>
    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>web.rest.Application</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Jersey Web Application</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>
以及作为@Service的实现

@Service
public class TranslationImportServiceImpl implements TranslationImportService{

@Inject
private ImportCandidateBuilder importCandidateBuilder;

@Override
public TranslationImportResult importTranslations(String inputName, InputStream inputStream, Long domainId,
                                                  String username, boolean allOrNothing) throws Exception {
    TranslationImportStatus ret;
    InputDeserializer inputDeserializer = InputDeserializerFactory.newInputDeserializer(inputName);
    List<InputTranslationBean> translationBeans = inputDeserializer.deserialize(inputStream);
    List<ImportCandidate> candidates = importCandidateBuilder.buildCandidates(domainId, translationBeans);
    insertStartImportEvent(candidates, inputName);
    translationImportOrchestrator.performTranslationsImport(candidates, username, allOrNothing);
    TranslationImportResult importResult = buildImportResult(translationImportOrchestrator);
    insertStopImportEvent(candidates, inputName);
    return importResult;
}
无法创建ImportCandidateBuilder类,因为没有默认构造函数。你有一个构造函数,但是这些参数应该来自哪里

public ImportCandidateBuilder(IDomainsBusinessServices domainService,
                              ICodeBusinessService codeService,
                              ILangBusinessService vlService, 
                              ITranslationBusinessService translationService) {
}
当您想要一个注入框架来创建服务时,那么要么需要一个将被调用的默认构造函数,要么需要一个带有参数的构造函数,该参数需要用@Inject注释,并且所有参数也必须绑定到DI容器

@Inject
public ImportCandidateBuilder(IDomainsBusinessServices domainService,
                              ICodeBusinessService codeService,
                              ILangBusinessService vlService, 
                              ITranslationBusinessService translationService) {
}

register(new AbstractBinder() {
    @Override
    public void configure() {
        bind(DomainsBusinessServices.class)
                .to(IDomainsBusinessServices.class).in(Singleton.class);
        //.. bind others
    }
});

你是在泽西2.27版还是2.26版?如果是这样的话,我知道我使用Jersey v2.6的解决方案,因为我的项目使用Java 7。如果你能提出一些解决方案,我会很高兴。你能给我看看AbstractBinder的导入吗?你能发布完整的stacktrace和builder类吗?当然可以@vikarjramun,import org.glassfish.hk2.utilities.binding.AbstractBinder;你绝对是对的,保罗。我认为在这种情况下,服务注释就足够了。我将进一步尝试,因为我的代码中有很多DIs的复杂逻辑。即使这样,关于如何处理构造函数,同样的规则仍然适用,但在这种情况下,我无法注入存储库类SessionFactory.class。@paul如何处理它?您需要将ServiceFactory绑定到DI系统。您可以使用工厂创建它并使用bindFactory。请看一些想法,@paul是否可以为这个案例编写一些代码?我尝试使用Factory和bindfactory,但我的injection sessionFactory再次返回为null。
@Service
public class ImportCandidateBuilder {

    private static Logger logger = LoggerFactory.getLogger(ImportCandidateBuilder.class);

    private IDomainsBusinessServices domainService;
    private ICodeBusinessService codeService;
    private ILangBusinessService vlService;
    private ITranslationBusinessService translationService;

    public ImportCandidateBuilder(IDomainsBusinessServices domainService, ICodeBusinessService codeService,
                                  ILangBusinessService vlService, ITranslationBusinessService translationService) {
        this.domainService = domainService;
        this.codeService = codeService;
        this.vlService = vlService;
        this.translationService = translationService;
    }

    public List<ImportCandidate> buildCandidates(Long domainId, List<InputTranslationBean> inputBeans) {
        Validate.notNull(domainId, "arg [domainId] is null");
        Validate.notEmpty(inputBeans, "arg [translations] is null or empty");

        List<ImportCandidate> ret = new ArrayList<>();

        Domains domain = fetchDomain(domainId);

        for (InputTranslationBean inputBean : inputBeans) {
            Tables table = fetchTable(domain, inputBean.getTableName());
            Codes code = (table == null) ? null : fetchCode(table, inputBean.getCodeName());
            Vl lang = fetchVl(inputBean.getLang());
            Trad translation = (code == null) ? null : fetchTranslation(code, lang);
            String transText = inputBean.getTranslation();
            String instructions = inputBean.getInstructions();
            ImportCandidate candidate = new ImportCandidate(domain, table, code, lang, translation, transText, instructions, inputBean);

            logger.debug("New import candidate built: [{}]", candidate);
            ret.add(candidate);
        }
        return ret;
    }
}
@Service
public class DomainsBusinessServices extends DefaultBusinessService 
                                     implements IDomainsBusinessServices
{
public Domains getDomainById(Long domainId, boolean fetchLangs,
            boolean fetchTables, boolean fetchCodes) {
        Criteria domainCriteria = getCurrentSession().createCriteria(Domains.class);
        domainCriteria.add(Restrictions.idEq(domainId));
        if(fetchLangs){
            domainCriteria.setFetchMode("Vls", FetchMode.JOIN);
        }
        if(fetchTables){
            domainCriteria.setFetchMode("Tableses", FetchMode.JOIN);            
        }
        if(fetchCodes){
            domainCriteria.setFetchMode("Codeses", FetchMode.JOIN);         
        }
        Domains domainVL = (Domains)domainCriteria.uniqueResult();
        if (domainVL != null) {
            Hibernate.initialize(domainVL.getVls());
        }
        return domainVL;
    }
}


@Service
public class DefaultBusinessService {

    @Inject
    private SessionFactory sessionFactory;

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    protected Session getCurrentSession(){
        return sessionFactory.getCurrentSession();
    }
}
public ImportCandidateBuilder(IDomainsBusinessServices domainService,
                              ICodeBusinessService codeService,
                              ILangBusinessService vlService, 
                              ITranslationBusinessService translationService) {
}
@Inject
public ImportCandidateBuilder(IDomainsBusinessServices domainService,
                              ICodeBusinessService codeService,
                              ILangBusinessService vlService, 
                              ITranslationBusinessService translationService) {
}

register(new AbstractBinder() {
    @Override
    public void configure() {
        bind(DomainsBusinessServices.class)
                .to(IDomainsBusinessServices.class).in(Singleton.class);
        //.. bind others
    }
});