Spring源码解析笔记
虽然现在已经普遍在用Springboot了,但是Spring还是得熟悉一下,永远都在用别人的而不知其所以然
1.基本Pom:
<!--Spring四大核心--> <!--Bean管理--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${springframework.version}</version> </dependency> <!--DI IOC--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${springframework.version}</version> </dependency> <!-- 全局的对象访问方式--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${springframework.version}</version> </dependency> <!--各类表达式 便捷操作--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${springframework.version}</version> </dependency> <!--扩展组件--> <!--aop--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${springframework.version}</version> </dependency> <!--aspect aop的经典应用--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${springframework.version}</version> </dependency> <!--消息传递处理--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> <version>${springframework.version}</version> </dependency> <!--消除了烦琐的JDBC编码和数据库厂商特有的错误代码解析。--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${springframework.version}</version> </dependency> <!--对象关系映射提供集成层 包括JPA和Hibernate 使用Spring-orm模块可以将这些O/R映射框架与Spring提供的所有其他功能结合使用,例如声明式事务管理功能。--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${springframework.version}</version> </dependency> <!--Java消息传递服务,包含用于生产和使用消息的功能--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> <version>${springframework.version}</version> </dependency> <!--普通pojo管理和声明式事务管理--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${springframework.version}</version> </dependency> <!--基本的Web开发集成功能,例如多文件上传功能、使用Servlet监听器初始化一个IOC容器以及Web应用上下文。--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${springframework.version}</version> </dependency> <!--Spring MVC框架提供了领域模型代码和Web表单之间的清晰分离--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${springframework.version}</version> </dependency> <!--提供了WebSocket和SocketJS的实现。--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-websocket</artifactId> <version>${springframework.version}</version> </dependency>
2.基本使用
·2.1 声明bean的配置 这里我们先使用最基础的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"> <bean id="studentBean" class="com.spring.modu1.Student"> <property name="age" value="1"/> <property name="name" value="张三"/> </bean> </beans>
2.2 基本流程
2.2.1声明实体
public class Student { private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
2.2.2 SpringBean简单加载流程
/** * Hello Spring! * */ public class App { public static void main( String[] args ) { //第一步声明资源加载配置 Resource resource =new ClassPathResource("BeanRegistry.xml"); //第二步建立全局工厂 DefaultListableBeanFactory defaultListableBeanFactory=new DefaultListableBeanFactory(); //构建资源读取器用来给工厂加载资源 XmlBeanDefinitionReader beanDefinitionBuilder= new XmlBeanDefinitionReader(defaultListableBeanFactory); //加载资源 beanDefinitionBuilder.loadBeanDefinitions(resource); //程序需要实体时直接从工厂拿对应的对象 Student bean = defaultListableBeanFactory.getBean(Student.class); System.out.println(bean.getAge().toString()+"---"+bean.getName().toString()); } }
3.Spring加载Bean基本过程说明:
-
把需要定义的Bean加载在Spring的配置文件中,包括注解或者Xml形式
-
需要通过Spring相关的Resource来加载对应的配置文件
-
显示声明一个Spring工厂,该工厂用来掌控我们在配置文件中配置的各种bean以及Bean之间的依赖管理及注入关系
-
需要定义一个配置信息读取器,该读取器用来读取我们之前配置的各种bean配置文件
-
读取器的作用是读取我们的配置文件信息,并且将读取的信息装配到我们之前所声明的工厂当中
-
上一流程中,我们需要将读取器与工厂及资源对象进行相应的关联处理
-
工厂配置的bean已装载完毕,可以供客户端直接调用获取客户需要的bean
4.逐步分析
4.1 第一步构建资源
4.1.1 Spring的资源在Spring中占据很大的一部分,Resource为资源的顶级接口,Spring通过各类资源的加载进行管理,比我除了我们演示的xml资源,还可以加载各类文件,URl资源登
Resource resource = new ClassPathResource("SpringBeanConfig.xml");
4.BeanFactoory 所有工厂最顶层的抽象
beanFactory 基本方法不多,其子类或实现根据具体的情景实现
public interface BeanFactory { String FACTORY_BEAN_PREFIX = "&"; Object getBean(String var1) throws BeansException; <T> T getBean(String var1, Class<T> var2) throws BeansException; Object getBean(String var1, Object... var2) throws BeansException; <T> T getBean(Class<T> var1) throws BeansException; <T> T getBean(Class<T> var1, Object... var2) throws BeansException; boolean containsBean(String var1); boolean isSingleton(String var1) throws NoSuchBeanDefinitionException; boolean isPrototype(String var1) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException; Class<?> getType(String var1) throws NoSuchBeanDefinitionException; String[] getAliases(String var1); }
5.源码阅读总结:
关于Spring Bean实例注册流程
- 定义好Spring的配置文件
- 通过Resources对象将Spring的配置文件进行抽象,抽象成一个具体的的Resource对象 如ClassPathResources
- 定义好将要使用的Bean工厂(各种BeanFactory)
- 定义XmlBeanDefinitionReader 对象,并将工厂的抽象方法作为参数传递进去,从而构建好亮着的关联关系
- 通过XmlBeanDefinitionReder对象来读取之前的所抽象的Resource对象
- 流程开始解析--
- 针对XMl文件进行各种元素的属性的解析,这里面,真正的解析是通过BeanDefinitionParserDelegate对象来完成的(委托模式)
- 通过BeanDefinitionParserDelegate 对象在解析Xml文件时,又用到了模板方法的设计模式(pre process post流程)
- 当所有的Bean标签元素都解析完毕后,开始定义一个BeanDefinition对象,该对象是一个非常重要的对象,里面容纳了构建一个Bean相关的所有属性
- BeanDefinition构建完成后,Spring又会创建一个BeanDefinitionHolder对象来持有BeanDefinition对象,它包含两个内容一个是Bean的名称,一个是BeanDefinition对象
- 工厂将会将解析出来的Bean信息放入到内部的一个CurrentHashMap中,该map的key是BeanName(唯一的),值是Beandefinition对象
- 调用Bean的解析完成的触发动作,从而触发相应的监听器方法的执行(
fireComponentRegistered方法 可选
)(使用了观察者模式)