gpt4 book ai didi

java - Spring在运行时添加一些bean到服务上下文

转载 作者:行者123 更新时间:2023-12-01 10:35:19 25 4
gpt4 key购买 nike

我正在创建 Spring DispatcherServlet 并以这种方式设置他的 Servlet 上下文:

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;


import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import java.io.IOException;
import java.util.*;

public class MyDispatcherBean implements InitializingBean {


@Autowired
private ApplicationContext applicationContext;

private DispatcherServlet dispatcherServlet;

private final String someContext = "some.xml";

private ServletContext servletContext;


public void execute(/* Do some code..*/) throws IOException {

/*
Do some code..
*/
try {
dispatcherServlet.service(/* ...*/);
} catch (ServletException e) {

}

}

public WebApplicationContext getServiceContext() {
return dispatcherServlet.getWebApplicationContext();
}
public void afterPropertiesSet() throws Exception {

dispatcherServlet = new DispatcherServlet() {

private static final long serialVersionUID = -7492692694742330997L;

@Override
protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext wac = createWebApplicationContext(applicationContext);
if (wac == null) {
wac = super.initWebApplicationContext();
}
return wac;
}

};

dispatcherServlet.setContextConfigLocation(someContext);
dispatcherServlet.init(new DelegatingServletConfig());
}

private class DelegatingServletConfig implements ServletConfig {

public String getServletName() {
return "myDispatcher";
}

public ServletContext getServletContext() {
return MyDispatcherBean.this.servletContext;
}

public String getInitParameter(String paramName) {
return null;
}

public Enumeration<String> getInitParameterNames() {
return Collections.enumeration(new HashSet<String>());
}
}

}

我这样创建这个bean:

<bean id="myDispatcher" class="some.package.MyDispatcherBean " />

然后在我的代码中的任何位置都可以存在任意数量的 bean,其代码可以获取“myDispatcher”bean 并在运行时将一些 bean 添加到 DispatcherServlet 的 servlet 上下文中:

public class ContextAdder implements InitializingBean {


@Autowired
private ApplicationContext applicationContext;


public String classPathToContext;

public void afterPropertiesSet() throws Exception {


DispatcherServlet dispatcherServlet = applicationContext.getBean("myDispatcher",DispatcherServlet.class);
XmlWebApplicationContext webApplicationContext = (XmlWebApplicationContext) dispatcherServlet.getWebApplicationContext();
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader((DefaultListableBeanFactory) webApplicationContext.getBeanFactory());
xmlReader.loadBeanDefinitions(new ClassPathResource(classPathToContext));

}

public ApplicationContext getApplicationContext() {
return applicationContext;
}

public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}

public String getClassPathToContext() {
return classPathToContext;
}

public void setClassPathToContext(String classPathToContext) {
this.classPathToContext = classPathToContext;
}
}

这些 bean 是这样创建的:

<bean id="adder1" class="stargate.sg_1.ContextAdder" depends-on="myDispatcher">
<property name="classPathToContext" value="Optimus.xml" />
</bean>

<bean id="adder2" class="stargate.atlantida.ContextAdder" depends-on="myDispatcher">
<property name="classPathToContext" value="StarShip.xml" />
</bean>

最后,我期望的行为是:每个 ContextAdder bean 将新 bean 添加到 myDispatcher bean 中的 DispatcherServlet 的 servlet 上下文中。

但我害怕某些时刻:

  1. 这个问题只有一个决定吗?
  2. 这是最好的吗?
  3. 每次当我向 DispatcherServlet 的 servletContext 添加新 bean 时,它会调用 ServletContext 甚至 ApplicationContext 的刷新吗?如果这是真的 - 对性能有影响吗?
  4. 所有生命周期都正确吗?

最佳答案

我相信有更好的方法,但将由您决定。

使用您的方法(实现InitializingBean),您将在bean定义阶段完成后以及构建bean之后调用bean创建代码。您的 bean 定义阶段非常简单(只需创建“myDispatcher”)。

我建议您在 bean 定义阶段创建/加载所有 bean 定义。实现此目的的一种方法是 Hook BeanFactory 后处理器(实现 BeanFactoryPostProcessor)。在此阶段,Spring 允许您修改现有的 bean 定义,更重要的是您可以添加更多 bean 定义。现在,当您离开此阶段时,所有 Bean 将在一个阶段中创建。该方法非常自然:创建 bean 定义 => 创建并连接 bean => 完成。

public class ContextAdder implements BeanFactoryPostProcessor {

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory factory)
throws BeansException {

XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader((BeanDefinitionRegistry)factory);

// I) LOAD BY PATTERN MATCHING
//PathMatchingResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver(factory.getBeanClassLoader());
//for (Resource resource : resourceResolver.getResources("com/.../*.xml"))
//reader.loadBeanDefinitions(resource);

// II) LOAD A SINGLE FILE AT A TIME
reader.loadBeanDefinitions(new ClassPathResource("com/../Optimus.xml""));
.....
}

也许您可以根据您的独特需求采用这个概念。

关于java - Spring在运行时添加一些bean到服务上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34776310/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com