通过工厂实例化 EJB

Instantiate EJB Via Factory

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

否则...是否有其他方法可以指示 Servlet 或 EJB 容器为我处理注释?就像某种螺栓,可以包含用于处理带注释 class/method/fields?

的反射分析的代码

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

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 的新实例,而不是容器通常这样做。有办法吗?

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

我刚刚发现了如何解决我的问题。首先,正如评论者指出的那样,我选择了 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注解。我选择不这样做。我只想在任何地方注入它以使用工厂实例化。