看到这个标题大家可能又想:哎,又一个重新发明轮子的人。在这里很想先声明一下,写这篇文章只是想让大家了解一下Spring到底是怎么运行的,并不是想重造轮子噢,希望大家看完这篇文章后能对Spring运作机制有更深入的了解,希望这篇文章对你有所帮助喔!好,言归正传,让我们来一起探索吧!
我们先从最常见的例子开始吧
Java代码
- public static void main(String[] args) {
- ApplicationContext context = new FileSystemXmlApplicationContext(
- "applicationContext.xml");
- Animal animal = (Animal) context.getBean("animal");
- animal.say();
- }
这段代码你一定很熟悉吧,不过还是让我们分析一下它吧,首先是applicationContext.xml
Java代码
- <bean id="animal" class="phz.springframework.test.Cat">
- <property name="name">
- <value>kitty</value>
- </property>
- </bean>
他有一个类phz.springframework.test.Cat =
Java代码
- public class Cat implements Animal {
- private String name;
- public void say() {
- System.out.println("I am " + name + "!");
- }
- public void setName(String name) {
- this.name = name;
- }
- }
实现了phz.springframework.test.Animal接口
Java代码
- public interface Animal {
- public void say();
- }
很明显上面的代码输出I am kitty!
那么到底Spring是如何做到的呢?
接下来就让我们自己写个Spring 来看看Spring运作机制吧!
首先,我们定义一个Bean类,这个类用来存放一个Bean拥有的属性
Java代码
- /* Bean Id */
- private String id;
- /* Bean Class */
- private String type;
- /* Bean Property */
- private Map<String, Object> properties = new HashMap<String, Object>();
一个Bean包括id,type,和Properties。
接下来Spring 就开始加载我们的配置文件了,将我们配置的信息保存在一个HashMap中,HashMap的key就是Bean 的 Id ,HasMap 的value是这个Bean,只有这样我们才能通过context.getBean("animal")这个方法获得Animal这个类。我们都知道Spring可以注入基本类型,而且可以注入像List,Map这样的类型,接下来就让我们以Map为例看看Spring是怎么保存的吧
Map配置可以像下面的
Java代码
- <bean id="test" class="Test">
- <property name="testMap">
- <map>
- <entry key="a">
- <value>1</value>
- </entry>
- <entry key="b">
- <value>2</value>
- </entry>
- </map>
- </property>
- </bean>
Spring运作机制中是怎样保存上面的配置呢?,代码如下:
Java代码
- if (beanProperty.element("map") != null) {
- Map<String, Object> propertiesMap = new HashMap<String, Object>();
- Element propertiesListMap = (Element) beanProperty
- .elements().get(0);
- Iterator<?> propertiesIterator = propertiesListMap
- .elements().iterator();
- while (propertiesIterator.hasNext()) {
- Element vet = (Element) propertiesIterator.next();
- if (vet.getName().equals("entry")) {
- String key = vet.attributeValue("key");
- Iterator<?> valuesIterator = vet.elements()
- .iterator();
- while (valuesIterator.hasNext()) {
- Element value = (Element) valuesIterator.next();
- if (value.getName().equals("value")) {
- propertiesMap.put(key, value.getText());
- }
- if (value.getName().equals("ref")) {
- propertiesMap.put(key, new String[] { value
- .attributeValue("bean") });
- }
- }
- }
- }
- bean.getProperties().put(name, propertiesMap);
- }
接下来就进入最核心部分了,让我们看看Spring 到底是怎么依赖注入的吧,其实依赖注入的思想也很简单,它是通过反射机制实现的,在实例化一个类时,它通过反射调用类中set方法将事先保存在HashMap中的类属性注入到类中。让我们看看具体它是怎么做的吧。
首先实例化一个类,像这样
Java代码
- public static Object newInstance(String className) {
- Class<?> cls = null;
- Object obj = null;
- try {
- cls = Class.forName(className);
- obj = cls.newInstance();
- } catch (ClassNotFoundException e) {
- throw new RuntimeException(e);
- } catch (InstantiationException e) {
- throw new RuntimeException(e);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- return obj;
- }
接着它将这个类的依赖注入进去,像这样
Java代码
- public static void setProperty(Object obj, String name, String value) {
- Class<? extends Object> clazz = obj.getClass();
- try {
- String methodName = returnSetMthodName(name);
- Method[] ms = clazz.getMethods();
- for (Method m : ms) {
- if (m.getName().equals(methodName)) {
- if (m.getParameterTypes().length == 1) {
- Class<?> clazzParameterType = m.getParameterTypes()[0];
- setFieldValue(clazzParameterType.getName(), value, m,
- obj);
- break;
- }
- }
- }
- } catch (SecurityException e) {
- throw new RuntimeException(e);
- } catch (IllegalArgumentException e) {
- throw new RuntimeException(e);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- } catch (InvocationTargetException e) {
- throw new RuntimeException(e);
- }
- }
最后它将这个类的实例返回给我们,我们就可以用了。我们还是以Map为例看看它是怎么做的,我写的代码里面是创建一个HashMap并把该HashMap注入到需要注入的类中,像这样,
Java代码
- if (value instanceof Map) {
- Iterator<?> entryIterator = ((Map<?, ?>) value).entrySet()
- .iterator();
- Map<String, Object> map = new HashMap<String, Object>();
- while (entryIterator.hasNext()) {
- Entry<?, ?> entryMap = (Entry<?, ?>) entryIterator.next();
- if (entryMap.getValue() instanceof String[]) {
- map.put((String) entryMap.getKey(),
- getBean(((String[]) entryMap.getValue())[0]));
- }
- }
- BeanProcesser.setProperty(obj, property, map);
- }
好了,这样我们就可以用Spring 给我们创建的类了,是不是也不是很难啊?当然Spring能做到的远不止这些,这个示例程序仅仅提供了Spring最核心的依赖注入功能中的一部分。这也是Spring运作机制中的一部分。
本文参考了大量文章无法一一感谢,在这一起感谢,如果侵犯了你的版权深表歉意,很希望对大家有帮助!
附件中包含该山寨Spring的源码,核心只有五个类,还有一个测试程序,phz.springframework.test.AnimalSayApp,可以直接运行。
相关推荐
如何通过spring自己的缓存机制缓存方法和数据,使系统性能更高!
Spring MVC 基于注解实例Spring MVC 基于注解实例Spring MVC 基于注解实例Spring MVC 基于注解实例Spring MVC 基于注解实例Spring MVC 基于注解实例Spring MVC 基于注解实例Spring MVC 基于注解实例Spring MVC 基于...
spring3.0mvc自学教程ppt+注解教程+注解实例+springmybatis教程+项目实例+中文api 初学(自学)着的不二法定,从入门到项目实例深入学习(浅-深)
【ASP.NET编程知识】浅谈.NET反射机制的性能优化 附实例下载.docx
spring配置文件实例
通过一个使用Spring、Spring Boot和Spring Cloud的小例子来说明如何构建微服务系统。 具体请看附件文件中的:readme.txt 和 [译]Spring构建微服务.png 访问地址:http://localhost:1111/ 运行顺序:...
spring 采用aop 的实例
spring aop
spring5.0的mvc项目实例,HelloWorld实例,基于eclipse oxygen jee 的maven project
spring的quartz使用实例,spring的quartz使用实例
Spring.Net的实例
spring boot 小实例 spring boot in action上的例子,spring boot 小实例 spring boot in action上的例子。
从工程实例浅谈中央空调系统消音降噪处理.docx
spring webflow 实例spring webflow 实例spring webflow 实例spring webflow 实例spring webflow 实例spring webflow 实例
spring mongodb mongodb实例,spring data mongodb 操作实例总结
spring-jdbcTemplate实例工程
Spring mvc、 Spring、 Spring jdbc 整合实例源码
cxf spring maven 实例 webservice
Spring+Dubbo 实例
spring_hibernate整合实例 spring_hibernate整合实例