【问题标题】:Instantiate EJB Via Factory通过工厂实例化 EJB
【发布时间】:2015-09-06 18:59:12
【问题描述】:

所以我有一个服务,我通过一个创建代理的工厂实例化它,以便它可以处理我在服务上的一些注释。所以我的问题是……JavaEE 有没有办法让我的依赖注入通过工厂实例化所述服务的实例,而不是 EJB 通常由服务器实例化。

否则...是否有其他方法可以指示 Servlet 或 EJB 容器为我处理注释?就像一个螺栓可以有代码来处理带注释的类/方法/字段的反射分析?

很抱歉,如果这个问题难以理解,我很难弄清楚如何提问。下面是一个可以用来实例化服务的工厂示例(通过代理)。

package com.trinary.test.service;

import java.lang.reflect.Proxy;

import com.trinary.security.owasp.proxy.OWASPMethodValidatorProxy;

public class TestServiceFactory {
    Class<?>[] interfaces = {TestService.class};

    public TestService createESignService() throws IllegalArgumentException, InstantiationException, IllegalAccessException {
        return (TestService)Proxy.newProxyInstance(
                this.getClass().getClassLoader(), 
                interfaces,
                new OWASPMethodValidatorProxy<TestService>(TestServiceImpl.class));
    }
}

如果在 servlet 中我可以做这样的事情,我会喜欢它:

package com.trinary.test.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.trinary.test.service.TestService;

public class TestServlet extends HttpServlet {
    private static final long serialVersionUID = -1778574173539761350L;

    @EJB protected TestService testService;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        System.out.println("PATH: " + req.getPathInfo());
        // ...

        resp.setContentType("text/html");
        resp.getWriter().append("<html><h1>TESTY TEST!</h1></html>");
    }
}

在上面您可以看到我如何将测试服务注入到我的 servlet 中。但是我希望 EJB 容器使用工​​厂来实例化 TestService 的新实例,而不是容器通常这样做。有没有办法做到这一点?

【问题讨论】:

  • 最好添加一些代码 sn-p 以了解您的问题以及您实际想要实现的目标。

标签: java dependency-injection ejb java-ee-7


【解决方案1】:

无法在注入点直接拦截@EJB,但您可以使用EJB 拦截器拦截实际bean 上的方法调用。如果您可以在客户端切换到 CDI @Inject,那么您可以使用 CDI 拦截器。此时,您可以使用 CDI 生产者方法来更好地控制注入到 servlet 中的对象。

【讨论】:

  • 我实际上刚刚发现我可以用 CDI 做我需要的事情(就像你说的那样)。然而,我使用它的路线涉及将我的工厂创建为托管 bean,然后在我的工厂方法上放置一个 @Produces 注释。然后当依赖注入时,它会从工厂方法中实例化它,而不是使用 new。
  • @deusprogrammer 当然,这听起来也可以。很高兴您找到了解决方案。
  • 谢谢!您的指导帮助了我!我会给你功劳=)。
【解决方案2】:

我刚刚发现了如何解决我的问题。首先,正如评论者指出的那样,我选择了 CDI 而不是 EJB(我需要了解两者之间的区别以及大多数应用程序服务器是否支持它)。

其次,我在工厂中的方法上使用了@Produces 注解,如下所示:

import java.lang.reflect.Proxy;
import javax.ejb.Stateless;
import javax.enterprise.inject.Default;
import javax.enterprise.inject.Produces;

import com.trinary.security.owasp.proxy.OWASPMethodValidatorProxy;

@Local
public class TestServiceFactory {
    Class<?>[] interfaces = {TestService.class};

    @Produces
    @Default
    public TestService createESignService() throws IllegalArgumentException, InstantiationException, IllegalAccessException {
        return (TestService)Proxy.newProxyInstance(
                this.getClass().getClassLoader(), 
                interfaces,
                new OWASPMethodValidatorProxy<TestService>(TestServiceImpl.class));
    }
}

然后在我的 servlet 中我现在可以这样做:

import java.io.IOException;

import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.trinary.test.service.TestService;

public class TestServlet extends HttpServlet {
    private static final long serialVersionUID = -1778574173539761350L;

    @Inject TestService testService;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        System.out.println("PATH: " + req.getPathInfo());

        testService.method(...);

        // ...

        resp.setContentType("text/html");
        resp.getWriter().append("<html><h1>TESTY TEST!</h1></html>");
    }
}

但是,如果您尝试将它与标记为托管 bean 的服务 TestService 一起使用,您会得到一个异常,因为除非您想使用 @Qualifer 注释,否则您想要实例化它的方式会很模糊。我选择不这样做。我只想在任何地方注入它以使用工厂进行实例化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-17
    • 2023-04-09
    • 1970-01-01
    • 2019-07-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多