如何获取Spring配置⽂件(加载⽣成Spring容器)
Spring容器是⽣成Bean的⼯⼚,我们在做项⽬的时候,会⽤到去获取的配置⽂件,然后从中拿出我们需要的bean出来,⽐如做⽹站⾸页,假设商品的后台业务逻辑都做好了,我们需要创建⼀个,在项⽬启动时将⾸页的数据查询出来放到application⾥,即在⾥调⽤后台商品业务逻辑的⽅法,也就是说我们需要在⾥获取Spring中配置的相应的bean。先把创建出来:
1. 创建InitDataListener
创建⼀个InitDataListener继承ServletContextListener:
1//@Component //是web层的组件,它是tomcat实例化的,不是Spring实例化的。不能放到Spring中
2public class InitDataListener implements ServletContextListener {
3
4private ProductService productService = null;//productService中定义了跟商品相关的业务逻辑
5
6 @Override
7public void contextDestroyed(ServletContextEvent event) {
8
9 }
10
11 @Override
12public void contextInitialized(ServletContextEvent event) {
13
14 }
15
16 }
并在l中配置该:
如上,productService中定义了商品的⼀些业务逻辑,并且这个productService是交给Spring管理的,那么我们如何得到这个对象呢?⾸先肯定的⼀点是:我们不能⾃⼰new出来,因为new出来的话就跟Spring的IoC没有关系了……主要有三种⽅式可以实现,我们先⼀个个分析,最后⽐较优劣。
2. 直接加载l⽂件
这种⽅式⽐较简单粗暴,不是要加载配置⽂件么?那好,我加载就是了,如下:
1//@Component //是web层的组件,它是tomcat实例化的,不是Spring实例化的。不能放到Spring中
2public class InitDataListener implements ServletContextListener {
3
4
5private ProductService productService = null; //productService中定义了跟商品相关的业务逻辑
6
7 @Override
8public void contextDestroyed(ServletContextEvent event) {
9
10 }
11
12 @Override
13public void contextInitialized(ServletContextEvent event) {
14// 获取业务逻辑类productService查询商品信息
15 ApplicationContext context = new ClassPathXmlApplicationContext("l");
16 productService = (ProductService) Bean("productService");
17 System.out.println(productService); //输出看看拿到了没有
18
19//下⾯是具体productService相关操作……
20 }
21
22 }
这种⽅法完全没问题,思路很清晰,先加载配置⽂件l,然后获取bean,但是启动tomcat后,我们看看控制台输出的信息:
到这⾥应该发现这种⽅式的弊端了,加载了两次配置⽂件,也就是说那些bean被实例化了两次,从打印的信息来看,是拿到我们⾃⼰加载配置⽂件是实例化的bean。这种⽅式明显不可取。
3. 从ServletContext中获取
从上⾯的⽅法中,我们最起码可以知道,Spring通过⾃⼰的已经加载过⼀次配置⽂件了,我们没必要再加载⼀次,那么很容易想到,如果知道Spring加载后放到哪⾥了,那我们就可以从那地⽅获取该配置⽂件,下⾯我们看下Spring加载配置⽂件的过程:
上图中(省略了⽆关的代码),ContextLoaderListener就是l中我们配置的Spring,它也实现了ServletContextListener并继承了ContextLoader。在中主要通过initWebApplicationContext⽅法来获取配置⽂件,并创建WebApplicationContext对象,在initWebApplicationContext⽅法⾥主要做两件
事:⼀是拿到Spring的上下⽂,⼆是把Spring上下⽂放到ServletContext中,并且键为:WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE。那么如何拿到Spring的上下⽂呢?是通过获取l中配置的Spring的路径,CONFIG_LOCATION_PARM其实是个字符串常量,就是上⾯l中配置Spring下⾯的:
<context-param>
<param-name>contextConfigLocation</param-name> <!--CONFIG_LOCATION_PARM就是contextConfigLocation-->
<param-value>l</param-value>
</context-param>
所以就很明显了,通过l中配置的路径拿到l,然后加载这个配置⽂件,实例化bean。
现在我们既然知道了Spring在加载配置⽂件后,把它放在了ServletContext中,那么我们就可以去这⾥⾯直接拿!
1//@Component //是web层的组件,它是tomcat实例化的,不是Spring实例化的。不能放到Spring中
2public class InitDataListener implements ServletContextListener {
3
4
5private ProductService productService = null;
6
7 @Override
8public void contextDestroyed(ServletContextEvent event) {
9// TODO Auto-generated method stub
10
11 }
13 @Override
14public void contextInitialized(ServletContextEvent event) {
15// 获取业务逻辑类查询商品信息
16
17// 解决⽅案⼆,项⽬在启动时,把Spring配置⽂件通过Spring的加载,存储到ServletContext中,我们只要在ServletContext中获取即可。
18 ApplicationContext context = (ApplicationContext) ServletContext()
19 .getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
20 productService = (ProductService) Bean("productService");
21 System.out.println(productService);
22 }
23
24 }
这样我们就可以拿到produceService的实例化对象了,这种⽅法好是好,就是getAttribute中的参数太长,也不知道当时程序员的脑门⼦被夹了还是咋地,估计是想不到其他更合适的名字了吧~
4. 通过Spring提供的⼯具类加载
也许开发Spring的⼤⽜们也意识到了这个参数名字太长了,于是他们提供了⼀个⽅法类,可以加载配置⽂件:
1public class InitDataListener implements ServletContextListener {
2
3
4private ProductService productService = null;
5
6 @Override
7public void contextDestroyed(ServletContextEvent event) {
8// TODO Auto-generated method stub
9
10 }
11
12 @Override
13public void contextInitialized(ServletContextEvent event) {
14// 获取业务逻辑类查询商品信息
15
16 WebApplicationContext context = ServletContext());
17 productService = (ProductService) Bean("productService");
18 System.out.println(productService);
19 }
20
21 }
其实,这⾥的getWebApplicationContext⽅法就是把上⾯的那个⽅法封装了⼀下⽽已,我们看看这个⽅法的源码就知道了:
public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
}
这样更加⽅便程序员调⽤,仅此⽽已……所以⼀般我们使⽤第三种⽅法来获取Spring的配置⽂件,从⽽获取相应的实例化bean。
代码实践:
Spring整合web项⽬时的问题:
启动服务器之后:
访问action时,每次访问都会重新加载spring配置⽂件,效率低下
解决⽅法:在服务器启动的时候,利⽤只加载⼀次spring配置⽂件即可。
在spring⾥边不需要⾃⼰写代码实现,框架已经做好了封装
只需要配置即可:但是配置时,需要导⼊⼀个spring整合web项⽬的jar包
创建⼀个web项⽬,要求每次访问action都⽆需加载新的xml⽂件,利⽤框架的实现只在服务器启动时加载⼀次xml配置,⽤于提⾼性能
开发准备,导⼊struts相关jar和spring框架IOC相关jar以及spring整合web项⽬的jar包
第⼀种⾃⼰完成的代码(不推荐,纯属娱乐)
1package org.lister;
2
3import javax.servlet.ServletContext;
4import javax.servlet.ServletContextEvent;
5import javax.servlet.ServletContextListener;
6
7import t.ApplicationContext;
8import t.support.ClassPathXmlApplicationContext;
9
10public class Lis implements ServletContextListener {
11
12public void contextDestroyed(ServletContextEvent arg0) {
13// TODO Auto-generated method stub
14
15 }
16public void contextInitialized(ServletContextEvent arg0) {
17// TODO Auto-generated method stub
18//服务器启动的时候创建ApplicationContext对象
19 ApplicationContext ac=new ClassPathXmlApplicationContext("l");
20
21//得到ServletContext对象
22 ServletContext ServletContext();
23
24//保存创建的ApplicationContext对象,在action中调⽤
25 sc.setAttribute("applicationcontext",ac);
27 }
1 <?xml version="1.0" encoding="UTF-8"?>
2 <web-app version="2.5"
3 xmlns="java.sun/xml/ns/javaee"
4 xmlns:xsi="/2001/XMLSchema-instance"
5 xsi:schemaLocation="java.sun/xml/ns/javaee
6 java.sun/xml/ns/javaee/web-app_2_5.xsd">
7 <welcome-file-list>
8 <welcome-file>index.jsp</welcome-file>
9 </welcome-file-list>
10
11 <!-- struts过滤器配置 -->
12 <filter>
13 <filter-name>struts2</filter-name>
14 <filter-class>org.apache.filter.StrutsPrepareAndExecuteFilter</filter-class>
15 <init-param>
16 <param-name>actionPackages</param-name>
17 <param-value&app.actions</param-value>
18 </init-param>
19 </filter>
20
21 <filter-mapping>
22 <filter-name>struts2</filter-name>
23 <url-pattern>/*</url-pattern>
24 </filter-mapping>
25
26 <!-- ⾃⼰的配置 -->
27 <listener>
28 <listener-class>org.lister.Lis</listener-class>
29 </listener>
30
31</web-app>
del;
2
3public class User {
4public void add(){
5 System.out.println("add。。。。。。。。。。。。");
6 }
7 }
1package org.action;
2
3import java.util.Map;
4
5import javax.servlet.ServletContext;
6import org.apache.struts2.ServletActionContext;
del.User;
8import t.ApplicationContext;
9
10import com.opensymphony.xwork2.ActionContext;
11import com.opensymphony.xwork2.ActionSupport;
12
13public class UserAction extends ActionSupport {
14
15 @Override
16public String execute() throws Exception {
17 System.out.println("进⼊action");
18// ApplicationContext ac=new ClassPathXmlApplicationContext("l");
19// User user=(Bean("user");
20// user.add();
21
22//得到ServletContext(上下⽂对象,即application对象)对象并且得到⾥边保存的applicationContext对象;
23 ServletContext servletContext = ServletContext();
24 ApplicationContext ac=(ApplicationContext) Attribute("applicationcontext");
25if(ac!=null){
26 User u=(User) ac.getBean("user");
27 u.add();
28 }
29
30/*
31 //以下代码也能实现
32 ActionContext Context();
33 Map Application();
34 ApplicationContext ac2=(ApplicationContext) ("applicationcontext");
35 if(ac2!=null){
36 User u2=(User) Bean("user");
37 u2.add();
38 }
39*/
40return NONE;
41 }
42 }
1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="/schema/beans"
3 xmlns:xsi="/2001/XMLSchema-instance"
4 xmlns:p="/schema/p"
5 xmlns:aop="/schema/aop" xsi:schemaLocation="
6 /schema/beans /schema/beans/spring-beans.xsd">
实例化bean的三种方式7 <bean id="user" class="del.User"></bean>
8 </beans>
在上边的程序中没有配置spring框架的,只配置了⾃⼰定义的,所以也实现了题⽬要求的功能:
服务器启动的时候加载了配置⽂件:
然后访问action截图如下:
即使反复请求,只会输出以上两句,控制台并没有打印其他内容,说明xml⽂件只加载了⼀次。
第⼆种:使⽤框架提供的监听机制,我们只需要配置即可,不多说直接上代码
1package org.dao;
2
3public class UserDao {
4public void add(){
5 System.out.println(".");
6 }
7 }
1package org.service;
2
3import org.dao.UserDao;
4
5public class Service {
6private UserDao userdao;
7
8public void setUserdao(UserDao userdao) {//使⽤set注⼊
9this.userdao = userdao;
10 }
11
12public void add(){
13 System.out.println(".");
14 userdao.add();
15 }
16 }
1 <?xml version="1.0" encoding="UTF-8"?>
2 <web-app version="2.5"
3 xmlns="java.sun/xml/ns/javaee"
4 xmlns:xsi="/2001/XMLSchema-instance"
5 xsi:schemaLocation="java.sun/xml/ns/javaee
6 java.sun/xml/ns/javaee/web-app_2_5.xsd">
7 <welcome-file-list>
8 <welcome-file>index.jsp</welcome-file>
9 </welcome-file-list>
10 <filter>
11 <filter-name>struts2</filter-name>
12 <filter-class>org.apache.filter.StrutsPrepareAndExecuteFilter</filter-class>
13 <init-param>
14 <param-name>actionPackages</param-name>
15 <param-value&app.actions</param-value>
16 </init-param>
17 </filter>
18 <filter-mapping>
19 <filter-name>struts2</filter-name>
20 <url-pattern>/*</url-pattern>
21 </filter-mapping>
22
23
24 <!-- 使⽤框架提供的监听机制需要配置下⾯代码 -->
25 <listener>
26 <listener-class>org.t.ContextLoaderListener</listener-class>
27 </listener>
28
29 <context-param>
30 <param-name>contextConfigLocation</param-name>
31 <param-value>l</param-value>
32 </context-param>
33</web-app>
1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans
3 xmlns="/schema/beans"
4 xmlns:xsi="/2001/XMLSchema-instance"
5 xmlns:p="/schema/p"
6 xmlns:aop="/schema/aop"
7 xsi:schemaLocation="/schema/beans
8 /schema/beans/spring-beans-3.0.xsd
9 /schema/aop
10 /schema/aop/spring-aop-3.0.xsd">
11 <bean id="ud" class="org.dao.UserDao"></bean>
12
13 <bean id="us" class="org.service.Service">
14 <property name="userdao" ref="ud"></property>
15 </bean>
16
17 </beans>
18
1package org.action;
2
3import java.util.Map;
4
5import javax.servlet.ServletContext;
6
7import org.apache.struts2.ServletActionContext;
8import t.ApplicationContext;
9import t.support.ClassPathXmlApplicationContext;
10import org.t.WebApplicationContext;
11import org.t.support.WebApplicationContextUtils;
12
13import com.opensymphony.xwork2.ActionSupport;
14
15import org.service.*;
16public class UserAction extends ActionSupport {
17
18 @Override
19public String execute() throws Exception {
20//ApplicationContext ac=new ClassPathXmlApplicationContext("l");
21
22//得到servletContext对象(上下⽂application对象)
23 ServletContext ServletContext();
24
25//从上下⽂对象中取得在服务器启动时创建的ApplicationContext对象
26//因为在服务器启动的时候就创建了⼀个applicationContext对象并且保存在了ServletContext中(上下⽂application中),
27//并且键为:WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
28 ApplicationContext ac=(Attribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); 29if(ac!=null){
30 Service s=(Bean("us");
31 s.add();
32 }else{
33 System.out.println("没有取得ApplicationContext对象");
34 }
35/*
36 WebApplicationContext context = ServletContext());
37 if(ac!=null){
38 Service s=(Bean("us");
39 s.add();
40 }else{
41 System.out.println("没有取得ApplicationContext对象");
42 }
43*/
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论