看到这个标题大家可能又想:哎,又一个重新发明轮子的人。在这里很想先声明一下,写这篇文章只是想让大家了解一下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缓存抽象是自Spring 3.1版本引入的,它提供了一个统一的API,支持多种缓存解决方案,如EhCache、Guava Cache...
Spring MVC 基于注解实例Spring MVC 基于注解实例Spring MVC 基于注解实例Spring MVC 基于注解实例Spring MVC 基于注解实例Spring MVC 基于注解实例Spring MVC 基于注解实例Spring MVC 基于注解实例Spring MVC 基于...
登录功能是Spring Security的基础,它提供了默认的登录页面和处理机制。你可以通过配置HttpSecurity来定制登录过程,例如设置登录URL、失败URL和成功处理器。Spring Security支持基于表单的身份验证,也支持OAuth2和...
总之,Spring Boot通过其强大的自动配置和依赖注入机制,使得在IDEA中实例化和使用DAO层变得非常简单。开发者只需要关注业务逻辑,而无需过多关注底层的数据访问细节。这大大提高了开发效率,也使得代码更加模块化和...
7. **Spring Cloud Gateway**:Spring Cloud的最新版本中,Zuul已被Gateway取代,Gateway提供更强大的路由功能和过滤器机制,能够处理更复杂的API管理和路由逻辑。 8. **Spring Cloud OpenFeign**:OpenFeign简化了...
通过一个使用Spring、Spring Boot和Spring Cloud的小例子来说明如何构建微服务系统。 具体请看附件文件中的:readme.txt 和 [译]Spring构建微服务.png 访问地址:http://localhost:1111/ 运行顺序:...
通过这个实例,学习者可以了解到如何在Eclipse中配置和运行一个基于Spring的Java项目,理解Spring框架的核心机制,以及如何利用MVC模式设计和实现Web应用。同时,也可以掌握Eclipse IDE的基本操作,提升Java编程和...
【标题】"CXF Spring Maven 实例"是一个关于如何整合并使用这些技术创建Web服务的教程。CXF是一个开源框架,主要用于构建和部署SOAP和RESTful Web服务,Spring则是一个广泛应用的Java企业级开发框架,而Maven是项目...
配置方面,Spring MVC的应用通常通过`web.xml`(传统方式)或Spring Boot的`application.properties`/`application.yml`来设置。现代的Spring项目更倾向于使用Spring Boot,它可以简化配置并提供开箱即用的功能。 ...
DWR提供了一些安全机制,如白名单限制,而Spring也有自己的安全框架可以帮助我们处理这些问题。同时,我们还可以通过缓存策略和异步调用来优化DWR的性能。 6. **异常处理**: 当服务器端发生错误时,DWR可以将异常...
在本文中,我们将深入探讨如何基于MyEclipse和MySQL环境学习Spring框架,并通过一系列实例来掌握其核心概念和功能。Spring是一个开源的Java平台,它为构建企业级应用提供了全面的框架支持,包括依赖注入、面向切面...
这个实例中的"mybatis整合spring实例(完整版)"文件可能包含了上述所有步骤的源代码,包括Spring的配置文件、MyBatis的配置文件、Mapper接口、XML文件以及相关的Java类。通过仔细阅读和理解这些代码,开发者可以...
在这个"spring连接数据库实例"中,我们将深入探讨Spring如何帮助开发者便捷地管理和操作数据库。 首先,让我们来了解Spring中的`DataSource`。`DataSource`是Java中用于存储和管理数据库连接的接口,它位于JDBC API...
在IT行业中,Spring框架是Java...通过上述知识点,我们可以理解Spring+JDBC实例是如何在实际项目中提升数据库操作的便捷性和可控性的。如果你想要深入学习,可以参考提供的博客链接或其他相关资料,进行实践和研究。
《深入浅出Spring Boot 2.x》是杨开振先生撰写的一本关于Spring Boot的权威指南,这本书旨在帮助读者深入理解并熟练运用Spring Boot 2.x框架。在压缩包文件中,包含了从第一章到第十七章的所有项目源码,这为读者...
在与Spring整合时,MyBatis的SqlSessionFactory可以通过Spring的Bean配置管理,实现事务控制和依赖注入。 Spring框架作为全能型的IoC(Inversion of Control)/DI(Dependency Injection)容器,负责管理和装配应用...
【标题】"maven+springMVC+spring security权限实例"是一个综合性的IT项目,它展示了如何使用Maven构建一个基于Spring MVC和Spring Security的权限管理应用。这个实例旨在帮助开发者快速理解并实践这三大技术在实际...
通过这个实例,开发者可以深入理解如何在Spring应用中集成Redis,并掌握相关配置和操作,提升应用的性能和响应速度。访问博主的博客(http://blog.csdn.net/u013142781)可以获得更详细的步骤和示例代码,帮助你快速...
本篇将深入探讨Spring 3.2.9的功能特性,以及如何通过具体实例来理解和应用这个版本。 一、Spring 3.2.9概述 Spring 3.2.9是Spring框架3.x系列的稳定版本,它在3.2.x系列中引入了诸多改进和优化,包括性能提升、更...
这个压缩包文件中的实例展示了如何利用这两者进行数据库登录验证,并且包含了SSL安全机制,这在现代网络应用中是非常关键的。 首先,让我们深入理解xfire和Spring的集成。Spring通过其`org.springframework....