Sping管理bean的原理

Posted ProSayJ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Sping管理bean的原理相关的知识,希望对你有一定的参考价值。

spring容器默认情况下,当服务启动时,解析配置文件,实例化文件中的所有类。

 

我们直接使用spring时,获取spring注入的bean是这样的,        

ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");

              MyService myService1 = (MyService) ctx.getBean("myService");

 

那下面我们模拟spring管理bean这个的过程,代码如下

 

1.         第一步,创建Java project,引入spring.jar

2.         创建spring.xml配置文件

 

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

 

</beans>

3.         创建接口MyService,只需要一个测试方法save

4.         创建实现类MyServiceImpl,控制台输出一句话

5.         创建一个自己的解析类MyClassPathXmlApplicationContext

 

主要是构造方法中的两步

  1     // 装载实例化bean
  2 
  3        private Map<String, Object> beanMap = new HashMap<String, Object>();
  4 
  5        // 装载配置文件的属性和值
  6 
  7        private List<MyBeans> beanlist = new ArrayList<MyBeans>();
  8 
  9       
 10 
 11        public MyClassPathXmlApplicationContext(String filename) {
 12 
 13               //第一步,解析spring配置文件
 14 
 15               readXml(filename);
 16 
 17               //第二步,通过反射,实例化所有注入bean
 18 
 19               initBeans();
 20 
 21        }
 22 
 23  
 24 
 25        /**
 26 
 27         * 通过反射机制,初始化配置文件中的bean
 28 
 29         */
 30 
 31        private void initBeans() {
 32 
 33               for (MyBeans bean : beanlist) {
 34 
 35                      try {
 36 
 37                             if (bean.getClassName() != null && !"".equals(bean.getClassName())) {
 38 
 39                                    beanMap.put(bean.getId(), Class.forName(bean.getClassName()).newInstance());
 40 
 41                             }
 42 
 43                      } catch (Exception e) {
 44 
 45                             e.printStackTrace();
 46 
 47                      }
 48 
 49               }
 50 
 51        }
 52 
 53  
 54 
 55        /**
 56 
 57         * 解析配置文件,把解析后的bean设置到实体中,并保持到list
 58 
 59         *
 60 
 61         * @param filename
 62 
 63         */
 64 
 65        private void readXml(String filename) {
 66 
 67               SAXReader reader = new SAXReader();
 68 
 69  
 70 
 71               Document doc = null;
 72 
 73               URL xmlpath = this.getClass().getClassLoader().getResource(filename);
 74 
 75               try {
 76 
 77                      Map<String, String> nsMap = new HashMap<String, String>();
 78 
 79                      nsMap.put("ns", "http://www.springframework.org/schema/beans");
 80 
 81                      doc = reader.read(xmlpath);
 82 
 83                      XPath xpath = doc.createXPath("//ns:beans//ns:bean");// 创建//ns:beans//ns:bean查询路径
 84 
 85                      xpath.setNamespaceURIs(nsMap);// 设置命名空间
 86 
 87                      List<Element> eles = xpath.selectNodes(doc);// 取得文档下所有节点
 88 
 89                      for (Element element : eles) {
 90 
 91                             String id = element.attributeValue("id");
 92 
 93                             String cn = element.attributeValue("class");
 94 
 95                             //自定义实体bean,保存配置文件中id和class
 96 
 97                             MyBeans beans = new MyBeans(id, cn);
 98 
 99                             beanlist.add(beans);
100 
101                      }
102 
103               } catch (Exception e) {
104 
105                      e.printStackTrace();
106 
107               }
108 
109  
110 
111        }
112 
113  
114 
115        public Object getBean(String beanId) {
116 
117               return beanMap.get(beanId);
118 
119        }
120 
121  
122 
123 6.         实体类
124 
125  
126 
127 package com.mooing.service;
128 
129  
130 
131 public class MyBeans {
132 
133        private String id;
134 
135        private String className;
136 
137  
138 
139        public MyBeans(String id, String className) {
140 
141               this.id = id;
142 
143               this.className = className;
144 
145        }
146 
147  
148 
149        public String getId() {
150 
151               return id;
152 
153        }
154 
155  
156 
157        public void setId(String id) {
158 
159               this.id = id;
160 
161        }
162 
163  
164 
165        public String getClassName() {
166 
167               return className;
168 
169        }
170 
171  
172 
173        public void setClassName(String className) {
174 
175               this.className = className;
176 
177        }
178 
179 }

 

 

7.         测试

 

1       MyClassPathXmlApplicationContext ctx = new MyClassPathXmlApplicationContext("spring.xml");
2 
3               MyService myService = (MyService) ctx.getBean("myService");
4 
5                myService.save();
6 
7  

 

总结:

自定义代码同样可以得到使用spring容器实例化的效果,也就是说,实际spring实例化管理bean时,也是经过两大步:第一,服务启动解析配置文件,并保存配置文件中的元素;第二,实例化所有元素,并提供获取实例方法。

以上是关于Sping管理bean的原理的主要内容,如果未能解决你的问题,请参考以下文章

Sping bean 的默认名称

Sping bean 的默认名称

Sping实战之通过JAVA代码装配Bean

sping揭秘3Spring容器中bean默认是保持一个实例

Sping bean的作用域

通过sping3 +Hibernate4+StrutsMVC实现 考试管理系统 逻辑 一 --Spring配置