现在用的是SSI框架,但在开发中遇到一些疑惑,希望高手给予解答。
因为是ssi的框架,项目在web.xml中定义了监听器,用于项目启动的时候就加载所有的bean
[code="xml"]
contextConfigLocation
classpath*:/config/spring/applicationContext.xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
[code="xml"]
但项目中有些类中,需要注入,一时想不出来好方法,就用了读取配置文件的方法,如下
ApplicationContext ctx = ClassPathXmlApplicationContext("配置文件");
但在配置定时器的时候发生了产生两个实例的问题;
我想问一下,
第一个问题:每次像ApplicationContext ctx = ClassPathXmlApplicationContext("配置文件");调用就重新实例话所有的bean,还是再次产生多个bean,造成多了一倍;这样做是不是会造成实例越来越多?
第二个问题,怎么查看项目启动后所有的已经实例化的bean?
什么叫“但项目中有些类中,需要注入”,什么意思?spring本身就可以用配置文件或者注解进行类的注入的啊。
为什么配置定时任务要启动两个IoC容器?直接把已经启动的IoC容器中的Bean取出来用不行么?
每次做ApplicationContext ctx = ClassPathXmlApplicationContext("配置文件");
这个操作,所有bean都要重新初始化一次,如果多次执行但是不销毁容器,那就只能等内存溢出了。
不明白你的问题,能否直接说你想实现什么功能?
要不就把用到的类也在xml中配置好当做bean来管理吧。
来学习。
你这样重新实例化了一个context,当你调用她里面的bean A对象时,才会实例化那bean A对象,而且在她所在的context里面只实例化一次,就相当于你new 出一个新对象放在堆里面一样,当你再次在引用这个context里的这个bean时,就相当于你的新句柄再次指向原来那个堆里的对象,而不是重新创建一个堆存储块。
还有你说的某些类需要注入,好像也没必要这样来重新再定义一个context吧
:oops: 如果你知道原理了也给我说下,我上次也在我的程序里实例化了一个
ApplicationContext ctx = ClassPathXmlApplicationContext("配置文件");
然后启动tomcat之后就飙出很多东西来,好像和我在web.xml定义的contextConfigLocation冲突似的,然后我就改用beanFactory了
web.xml 文件中一般包括 servlet, spring, filter, listenr的配置。
加载顺序是 先加载filter 后加载spring,则filter中初始化操作中的bean为null;
首先可以肯定 加载顺序与他们在web.xml 文件中的先后顺序无关。
web.xml 中 listener 和 serverlet 的加载顺序为 先 listener 后serverlet
最终得出结果:先 listener >> filter >> servlet >> spring
所以,如果过滤器中要使用到 bean,可以将spring 的加载 改成 Listener的方式
org.springframework.web.context.ContextLoaderListener
网上的资料这么说的, :oops:
学习。
楼主既然有一些类需要注入,那么为什么不专门用一个类来做这件事,把需要注入的东西放到内存里(用hashMap封装好 id作为key),然后需要注入时,通过这个 bean的id 来从map中取得你需要的实体类实例化。
这样项目运行时,就只有两个地方存放所有的实例了,而且Map取东西也很快。
对于LZ提的问题,我也答不具体。只是提提参考意见。
对于部分需要手动注入,部分需要spring配置注入,解决方案想和大家一起讨论讨论:
小弟的是:
例如:
[code="java"]
class A extends AllFather{
public A (){
this.setServiceName('spring中bean的id')
}
}
[/code]
对于setServiceName(...)是在父类AllFather中的统一实现的
[code="java"]
class AllFather{
public Service serviceName ;
public Map map;
public AllFather(){
//调用map的填充方法
}
public void setServiceName(String id){
this.serviceName =(Service)map.get(id)
}
private void setMap(String xmlsrpingfilurl){
//将bean都都封装到map中
}
}
[/code]
估计其中对于什么时候调用父类的方法, 这个父类是静态或者其他的等等需要继续改完善。讨论讨论。
你的配置没有问题啊,大家都是这样用的。注入的可以像下面这么做:
[code="java"]
public class ExampleBusinessObject {
// properties and collaborators
public void doIt() {
// do the actual work
}
}
[/code]
[quote]容器销毁? ApplicationContext怎么销毁?? [/quote]
在非Web应用中,手工加载Spring IoC容器,不能用ApplicationContext,要用AbstractApplicationContext。用完以后要记得调用ctx.close()关闭容器。如果不记得关闭容器,最典型的问题就是数据库连接不能释放。
代码如下:
[code="java"]
AbstractApplicationContext ctx= ClassPathXmlApplicationContext("配置文件");
//测试代码...
ctx.close();
[/code]
[code="java"]public class SystemInitListener implements ServletContextListener, HttpSessionListener, HttpSessionAttributeListener {
@SuppressWarnings("all")
public void contextInitialized(ServletContextEvent sce) {
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(sce.getServletContext());
DefaultBiz defaultBiz = (DefaultBiz) wac.getBean("defaultBizImpl");
}[/code]
自定义一个Listener,如上,在web.xml中加入
com.jax.listener.SystemInitListener