[Java] Spring 原理
IOC(Inverse of Control)控制反转
- 依赖对象的获得被反转了,由自己创建变为从IOC容器获取
- 优点
- 代码更简介,不需要new对象
- 面向接口编程,使用者与具体类解耦,易扩展
- 方便进行AOP编程,在IOC容器中进行AOP
- 功能:创建、管理类的实例,向使用者提供实例
- 工厂模式应用,IOC容器也称为Bean工厂
- Bean:组件,类的对象
- Bean工厂设计
- 接口:对外提供Bean实例,getBean()
- 参数:创建产品的类
- 返回值:各种类型Bean,Object
- Bean定义:告诉Bean工厂如何创建某类Bean,可根据获取对象方式扩充
- new构造方法:类名
- 静态工厂方法:工厂类名、工厂方法名
- 成员工厂方法:工厂Bean名,工厂方法名
- 单例
- 特定初始化、销毁逻辑的执行
- Bean定义注册接口
- 注册、获取Bean定义
- 设计过程
- 定义Bean工厂,用来创建Bean
- Bean定义,告诉Bean工厂如何创建Bean
- Bean注册
默认Bean工厂实现
- 实现定义信息注册
- 用Map存储BeanName和BeanDefinition
- 重名的处理
- 实现Bean工厂getBean
- 通过反射创建对象
- BeanFactory和FactoryBean
- 实现初始化方法执行
- doInit(),反射调用初始化方法
- 实现单例
- 通过名字取实例,用Map保存
- 有则返回,无则创建
- 保证单例,加锁+双重检查(DCL)
- volatile:保证变量可见性,防止指令重排
- 实现别名
- Map<alias,name>
- 按照Type获取Bean
- 注册Bean定义时,在registerBeanDefinition()中建立映射关系
- BeanDefination获取Class:在所有Bean定义注册完后,实例化单例Bean前
- DefaultBeanFactory中增加buildTypeMap()
- 遍历name对应的Bean定义,找出Primary,获取实例,没有Primary或有多个则抛异常
- 实现容器关闭时执行单例的销毁方法
- Bean生命周期
- 单例Bean:容器关闭时销毁
- 原型Bean:由使用者管理
- 程序结束
- 自然结束
- 主动关停
- Bean生命周期
- 提前实例化
- PreBuildBeanFactory
- Bean增加别名支持
- Bean除了唯一标识的名称外,还可以有别名
- BeanDefinition中有BeanClass属性
- AliasRegistry接口,包含方法:注册、移除、判断是否别名、获取原始名
- aliasMap<String,String>
- BeanFactory增加可按Type获取Bean对象的功能
- 通过Tpye找beanName,再获取Bean实例
- Type和Bean是一对多关系
- <T> getBeansOfType(Class<T>):Map<String,T>
- <T> getBeansListOfType(Class<T>):List<T>
- 优化,提前把Type和Bean的关系找出来,用Map<Tpye,beanName>缓存
- 所有Bean定义注册完后,实例化单例Bean前构建tpyeMap
- 遍历beanDefinitionMap,buildTpyeMap()
DI(Dependency injection)依赖注入
- 哪些地方有依赖
- 构造参数依赖
- 属性依赖
- 依赖注入本质
- 给构造参数赋值
- 给属性赋值
- 直接值的类型
- 基本数据类型值,String
- 数组,集合,Map
- 如何告诉Bean工厂该给入什么构造参数值,即如何定义参数依赖
- 用LIst存储,按参数顺序放入
- BeanReference:说明Bean依赖,即依赖哪个Bean,可以按name或Type依赖
- 如何定义属性依赖
构造参数依赖实现
- BeanFactory中实现构造参数依赖注入
- 静态工厂方法、工厂方法中参数依赖处理一样
- 在BeanDefination中增加方法,缓存原型Bean的构造方法或工厂方法
- 循环依赖
- 在doGetBean()中加入一个正在创建Bean的记录,每个Bean开始创建时加入该记录中
- getBean时先看bean是否在记录中,如果是则构成了循环依赖,抛出异常
- 创建完后从记录中移除
- 并发问题
- a和依赖a的b同时创建,报错
- 线程隔离
- ThreadLocal<Set<String>> buildingBeanRecorder
属性依赖实现
- 某个属性依赖什么
- 某个值
- 如何描述一个属性依赖
- 属性名、值,定义一个类表示两个值
- 多个属性依赖怎么存放
- LIst
- 属性值情况和构造函数参数值一样吗
- 一样,直接值或Bean依赖
- DefaultBeanFactory中实现属性依赖
- 何时进行属性依赖注入
- Bean示例创建好后,执行初始化方法前
- 属性依赖可以循环吗
- 自己new可以,IOC容器中不可以
AOP(面向切面)
- 定义
- 在不改变代码的情况下,对类方法进行功能增强
- 在框架中向用户提供AOP功能,通过AOP对类方法进行功能增强
- 方式
- 编译时增强/运行时增强
- 动态代理
- 术语
- Advice(通知):增强的功能(用户提供)
- Join Points(连接点):可选的方法点(用户提供)
- Pointcut(切入点):选择切入的方法点(用户提供)
- Aspect(切面):选择的方法点+增强的功能
- Introduction(引入):添加新的方法、属性到已存在的类中
- Weaving(织入):不改原类的代码,加入功能增强
- Advice
- 用户提供
- 变化:不同增强需求,实现逻辑不同
- 时机:可选择在方法功能前、后、异常时进行功能增强
- Before(前置)
- After(后置)
- AfterReturn(后置)
- Around(环绕)
- 异常处理
- 多重:同一个切入点可有多重增强
- Pointcut
- 用户性:用户指定
- 变化:灵活
- 多点:用户可选择多个点进行增强
- 描述信息:xx类的xx方法(方法签名)
- 表达式:决定是否要对xx类的xx方法进行增强
- 设计
- 切点有什么属性?定义表达式
- 对外提供什么行为?方法
- 用来做什么?对类、方法进行匹配,切点提供匹配类/方法的行为
- Weaving
- 无侵入性,不改原类代码
- 在框架中实现
- 将用户提供的增强功能加到指定的方法上
- 创建bean实例时,bean初始化后,进行增强,返回代理对象创建的实例
- 一次写好BeanFactory后,不改代码实现灵活扩展
- 在各节点加入扩展点,加入注册机制
- 观察者模式(监听模式),6个扩展点,6个主题/观察者
- 如何判断Bean实例是否要增强
- 获取bean的类及所有方法
- 遍历Advisor,取advisor中的pointcut来匹配类,方法
- 动态代理的实现方式,只能对接口创建代理对象,jdk/cglib
- 如有增强的advice,用责任链模式执行增强
- 面向接口
- 用户(开发人员)通过接口实现不同逻辑
Bean定义配置化
- 对象少时,可通过new,set
- 对象多时,通过xml配置bean,或通过注解实现
- 解析xml/注解进行bean定义
- xml方式
- 定义xml规范
- 解析xml,完成bean定义注册
- 注解方式
- 定义注解,哪些类/属性需要依赖注入
- 代码扫描,解析注解,完成bean定义注册
- 结合反射完成功能
- 定义
- @Component:类要不要配置为bean
- @Scope
- @Primary
- @Bean:通过工厂方法创建bean
- @PostConstruct、@PreDestroy:初始化、销毁方法
- @Autowired、@Value:构造参数、属性依赖
- @Qualifier
ApplicationContext
- 获取bean定义,扫描包,注册bean
- 外观模式(门面模式),为框架定义一个更简单的统一使用页面
手写Spring
- 初始化阶段
- 加载配置文件
- 扫描相关类
- 实例化相关类
- 实现依赖注入
- 初始化HandlerMapping
- 运行阶段
- 通过url找到method
- 提取request的参数
- 提取method的形参列表
- 给method的实参列表赋值
- 反射调用method,返回结果
常用类
- ApplicationContext
- 创建对象
- 将对象缓存到IoC容器中(Map)
- 执行依赖注入DI
- BeanDefinition:配置文件封装(yml、properties、xml、json)
- BeanDefinitionReader:读取配置信息(工具类)
- BeanWrapper:Bean实例包装类
- getbean()
- 拿到BeanName的配置信息,即BeanConfiguration
- 实例化对象
- 将实例化后的对象封装成BeanWrapper
- 将BeanWrapper缓存到IoC容器中
- 完成依赖注入
参考
IOC
https://blog.csdn.net/love_everybody/article/details/79836136
Java反射技术——字段的获取
https://blog.csdn.net/zlb824/article/details/7494300
web.xml文件的作用及基本配置
https://www.cnblogs.com/fnlingnzb-learner/p/6560774.html
jetty安装
https://www.jianshu.com/p/2412ccfb36e1
IDEA+Tomcat+Maven
https://blog.csdn.net/limshirley/article/details/86682364
静态工厂方法和实例工厂方法
https://www.cnblogs.com/yonyong/p/9405963.html
原型bean和单例bean
https://blog.csdn.net/yangshengwei230612/article/details/107860872
getbean()参数
https://zhidao.baidu.com/question/243416268635183644.html
[Java] Spring 原理的更多相关文章
- 转载:把你的精力专注在java,jvm原理,spring原理,mysql锁,事务,多线程,大并发,分布式架构,微服务,以及相关的项目管理等等,这样你的核心竞争力才会越来越高
https://developer.51cto.com/art/202001/608984.htm 把你的精力专注在java,jvm原理,spring原理,mysql锁,事务,多线程,大并发,分布式架 ...
- 从零开始学 Java - Spring 集成 Memcached 缓存配置(一)
硬盘和内存的作用是什么 硬盘的作用毫无疑问我们大家都清楚,不就是用来存储数据文件的么?如照片.视频.各种文档或等等,肯定也有你喜欢的某位岛国老师的动作片,这个时候无论我们电脑是否关机重启它们永远在那里 ...
- 从零开始学 Java - Spring MVC 实现跨域资源 CORS 请求
论职业的重要性 问:为什么所有家长都希望自己的孩子成为公务员? 答:体面.有权.有钱又悠闲. 问:为什么所有家长都希望自己的孩子成为律师或医生? 答:体面.有钱.有技能. 问:为什么所有家长都不怎么知 ...
- spring原理案例-基本项目搭建 02 spring jar包详解 spring jar包的用途
Spring4 Jar包详解 SpringJava Spring AOP: Spring的面向切面编程,提供AOP(面向切面编程)的实现 Spring Aspects: Spring提供的对Aspec ...
- spring原理案例-基本项目搭建 03 创建工程运行测试 spring ioc原理实例示例
下面开始项目的搭建 使用 Java EE - Eclipse 新建一 Dynamic Web Project Target Runtime 选 Apache Tomcat 7.0(不要选 Apache ...
- Java Spring Boot VS .NetCore (四)数据库操作 Spring Data JPA vs EFCore
Java Spring Boot VS .NetCore (一)来一个简单的 Hello World Java Spring Boot VS .NetCore (二)实现一个过滤器Filter Jav ...
- Java Spring Boot VS .NetCore (八) Java 注解 vs .NetCore Attribute
Java Spring Boot VS .NetCore (一)来一个简单的 Hello World Java Spring Boot VS .NetCore (二)实现一个过滤器Filter Jav ...
- Java Spring Boot VS .NetCore (九) Spring Security vs .NetCore Security
Java Spring Boot VS .NetCore (一)来一个简单的 Hello World Java Spring Boot VS .NetCore (二)实现一个过滤器Filter Jav ...
- spring 原理
1.spring原理 内部最核心的就是IOC了,动态注入,让一个对象的创建不用new了,可以自动的生产,这其实就是利用java里的反射,反射其实就是在运行时动态的去创建.调用对象,Spring就是在运 ...
随机推荐
- kubernetes1.17.2结合ceph13.2.8部署gitlab12.1.6
[root@bs-k8s-ceph ~]# ceph -s cluster: id: 11880418-1a9a-4b55-a353-4b141e2199d8 health: HEALTH_OK se ...
- lms框架分布式事务使用简介
lms框架的分布式事务解决方案采用的TCC事务模型.在开发过程中参考和借鉴了hmily.使用AOP的编程思想,在rpc通信过程中通过拦截器的方式对全局事务或是分支事务进行管理和协调. 本文通过lms. ...
- IIS误删了默认网站,恢复方法
有时候安装好IIS后,会不小心把IIS的默认网站删除.重新去新建可能会出现一些错误例如"提示文件已存在无法执行"等奇怪的错误,下面是具体的默认网站的恢复方法 找到目录C:\wind ...
- 如何使用yolov3训练自己的数据集
博客主要结构 1. 如何在ubuntu18.04上安装yolo 2 .如何配置yolov3 3 .如何制作自己的训练集测试集 4 .如何在自己的数据集上运行yolov3 1. 在ubuntu18.04 ...
- 给出N个字符串恰好由三位字母(大小写)组成,再给出M个查询字符串,问每个查询字符串在N个字符中出现的次数。
1 #include<cstdio> 2 const int maxn = 100; 3 char S[maxn][5], temp[5]; 4 int hashTable[52 * 52 ...
- Leedcode算法专题训练(位运算)
https://www.cnblogs.com/findbetterme/p/10787118.html 看这个就完事了 1. 统计两个数的二进制表示有多少位不同 461. Hamming Dista ...
- 『Spring Boot 2.4新特性』减少95%内存占用
节省 95%的内存占用,减少 80%的启动耗时. GraalVM 是一种高性能的虚拟机,它可以显著的提高程序的性能和运行效率,非常适合微服务.最近比较火的 Java 框架 Quarkus 默认支持 G ...
- Qt中检查槽函数connect是否正确
环境:VS2017+Qt插件 一般情况下VS+QT环境下运行的QT程序输出信息需要在调试模式的输出栏可以看到,由于太多信息所以导致查看不方便(当然也可以在筛选选项中筛选信息). 有更方便查看输出信息的 ...
- 安全开发Java:日志注入,并没那么简单
摘要:当web工程比较大,历史代码较多时, 应当使用log4j2框架的能力来修改日志注入问题,而不是按照有些博文里写的逐个进化参数的方式. 案例故事 某个新系统上线了,小A在其中开发了个简单的登录模块 ...
- 本地+分布式Hadoop完整搭建过程
1 概述 Hadoop在大数据技术体系中极为重要,被誉为是改变世界的7个Java项目之一(剩下6个是Junit.Eclipse.Spring.Solr.HudsonAndJenkins.Android ...