Spring注入Servlet
所以我看到了这个问题:
Springdependency injection到其他实例
并想知道我的方法是否会成功。
1)在我的Spring应用程序上下文中声明bean
2)覆盖我的servlet的init方法,如下所示:
@Override public void init(ServletConfig config) throws ServletException { super.init(config); ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); this.apiData = (ApiData)ac.getBean("apiData"); this.apiLogger = (ApiLogger)ac.getBean("apiLogger"); }
这个工作还是Spring还没准备好在Web应用程序部署中将bean交付给我的servlet? 我是否必须做一些更传统的事情,比如把bean放在web.xml
?
您要做的是使每个Servlet
都有自己的ApplicationContext
实例。 也许这就是你想要的,但我对此表示怀疑。 ApplicationContext
对于ApplicationContext
应该是唯一的。
执行此操作的适当方法是在ServletContextListener
设置ApplicationContext
。
public class SpringApplicationContextListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); sce.getServletContext().setAttribute("applicationContext", ac); } ... // contextDestroyed }
现在,所有servlet都可以通过ServletContext
属性访问相同的ApplicationContext
。
@Override public void init(ServletConfig config) throws ServletException { super.init(config); ApplicationContext ac = (ApplicationContext) config.getServletContext().getAttribute("applicationContext"); this.apiData = (ApiData)ac.getBean("apiData"); this.apiLogger = (ApiLogger)ac.getBean("apiLogger"); }
我想利用Sotirios Delimanolis提供的解决方案,但为混合添加透明自动assembly。 我们的想法是将普通的servlet转换为支持autowire的对象。
所以我创建了一个父抽象servlet类,它检索Spring上下文,获取和支持自动assembly的工厂,并使用该工厂自动assemblyservlet实例(实际上是子类)。 我还将工厂存储为实例变量,以防子类需要它。
所以父抽象servlet看起来像这样:
public abstract class AbstractServlet extends HttpServlet { protected AutowireCapableBeanFactory ctx; @Override public void init() throws ServletException { super.init(); ctx = ((ApplicationContext) getServletContext().getAttribute( "applicationContext")).getAutowireCapableBeanFactory(); //The following line does the magic ctx.autowireBean(this); } }
一个sevlet子类看起来像这样:
public class EchoServlet extends AbstractServlet { @Autowired private MyService service; @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.getWriter().println("Hello! "+ service.getMyParam()); } }
请注意,EchoServlet唯一需要做的就是在常见的Spring实践中声明一个bean。 魔术是在超类的init()方法中完成的。
我还没有彻底测试过。 但是它使用了一个简单的bean MyService,它也可以从Spring管理的属性文件中获取一个自动assembly的属性。
请享用!
注意:
最好用Spring自己的上下文监听器加载应用程序上下文,如下所示:
contextConfigLocation classpath:applicationContext.xml org.springframework.web.context.ContextLoaderListener
然后像这样检索它:
WebApplicationContext context = WebApplicationContextUtils .getWebApplicationContext(getServletContext()); ctx = context.getAutowireCapableBeanFactory(); ctx.autowireBean(this);
只需要导入spring-web库,而不是spring-mvc。
到目前为止,这里的答案只对我有用。 特别是带有@Configuration注释的类被忽略了,我不想使用xml配置文件。 以下是我使用基于Spring(4.3.1)注释的设置进行注射工作的方法:
在web-app下的web.xml中引导AnnotationConfigWebApplicationContext。 作为参数,您需要contextClass和contextConfigLocation(您的带注释的配置类):
contextClass org.springframework.web.context.support.AnnotationConfigWebApplicationContext contextConfigLocation com.example.config.AppConfig org.springframework.web.context.ContextLoaderListener
然后覆盖servlet中的init方法。 我使用了一个扩展HttpServlet的抽象类,所以我不必在每个servlet中重复它:
@Configurable public abstract class MySpringEnabledServlet extends HttpServlet { @Override public void init( ServletConfig config) throws ServletException { super.init(config); SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); } [...] }
最后我在web.xml中提到的AppConfig类中有我的主要配置:
@Configuration @ComponentScan(basePackages = "com.example") @Import( { SomeOtherConfig.class }) public class AppConfig { }
dependend类注释:
@Component public class AnnotatedClassToInject
并通过自动assembly注入我的servlet:
@Autowired private AnnotatedClassToInject myClass;
Spring独立于Servlet启动。 在spring读取bean xml之后,它将准备好传递bean。 所以在下面的声明之后,bean已经可用了
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
另外,正如@LuiggiMendoza所指出的,每个ApplicationContext
都会创建/维护自己的bean,因此创建ApplicationContext
一次并从不同的servlet 重用它(而不是在Servlet的init()
方法中创建它们init()
总是好的。
- ejb与客户端工件 – 运行时依赖?
- “@inject”-ed属性保持为null
- 基于没有单例的HttpRequest的jersey 2上下文注入
- 为什么Spring的@Configurable有时可以工作,有时候不工作?
- Android Dagger 2 Dependency没有被注入
- 匕首2:如何注入Map <Class ,Provider >
- 创建新对象和dependency injection之间的区别
- 哪个Java Web Framework最适合Google Guice?
- 当@Context用于setter / field / constructor注入时,HK2 Factory在Jerseyfilter之前调用