通过工厂实例化 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注解。我选择不这样做。我只想在任何地方注入它以使用工厂实例化。
所以我有一个服务,我通过一个创建代理的工厂实例化它来挂钩,这样它就可以处理我在服务上的一些注释。所以我的问题是……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注解。我选择不这样做。我只想在任何地方注入它以使用工厂实例化。