第五周 Spring框架
一、Spring框架设计
Spring framework 6大模块

1.1 Spring AOP
AOP: 面向切面编程
Spring 早期版本的核心功能,管理对象声明周期和对象装配
为了实现管理和装配,一个自然的想法就是,加一个中间层代理(字节码增强)来实现所有对象的托管
IoC:控制反转
IoC是一个宽泛的概念,而DI(依赖注入)是其中的一种实现方式。
从对象A直接引入和操作对象B,变成对象A只需要依赖一个接口IB,系统启动和装配阶段,把IB接口的实例对象注入到对象A,这样A就不需要依赖一个IB接口的具体实现。
从而达到修改配置文件,就可以在运行时替换成注入IB接口的其他实现类的一个对象实例。
思考:Spring怎么解决循环依赖?
当实例A依赖B,实例B依赖A时。就构成了循环依赖。Spring解决的思路就是先构造一个"早期"对象,对象的属性还没填充,然后将这个早期对象注入容器。让B完成实例化,此时A就能获取到B的引用,完成了实例化。
具体实现是通过Spring的三级缓存。
什么类型的循环依赖Spring无法处理?
答:双方都是构造函数注入或主bean对象(Spring启动中先加载的对象)使用构造函数注入。
构造器注入和setter注入在创建bean时候的区别
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
///隐藏无用代码
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}
//获取构造器注入
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
//如果ctors不为空,就是构造器注入
if (ctors != null) {
return
//需要去创建构造器里依赖的bean,此时还没实例化出对象来放入三级缓存
autowireConstructor(beanName, mbd, ctors, null);
}
//不是构造器注入,就可以实例化出一个bean来,并放入三级缓存里面了。
return instantiateBean(beanName, mbd);
}
Spring AOP的实现方式:
动态代理
接口类型,默认使用JDK动态代理。非接口类型默认使用CGlib。

如果接口类型想改为用CBlib动态代理:
spring xml:
<aop:aspectj-autoproxy expose-proxy="true" proxy-target-class="true"/>
spring boot 配置文件:
# 增加@EnableAspectJAutoProxy
spring.aop.auto=true
# 开启CGLIB代理
spring.aop.proxy-target-class=true
字节码增强

1.2 Spring Bean

Bean的加载过程:
- 创建对象
- 属性赋值
- 初始化
- 注销接口注册
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// 1. 实例化bean
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
/**
省略部分代码
**/
// Initialize the bean instance.
Object exposedObject = bean;
try {
//2.属性赋值
populateBean(beanName, mbd, instanceWrapper);
//3.初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
/**
省略部分代码
**/
// 4.销毁的回调方法
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
Bean的初始化过程:
- 检查Aware装配
- BeanPostProcessors前置处理
- init方法
- BeanPostProcessors后置处理
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
//1.检查Aware接口并设置相关依赖
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//2.BeanPostProcessor前置处理
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//若有init方法,则执行
//若实现了InitializingBean接口,则执行
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//BeanPostProcessor后置方法处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
第五周 Spring框架的更多相关文章
- 跟着刚哥学习Spring框架--AOP(五)
AOP AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.OOP引入 ...
- 23种设计模式之自定义Spring框架(五)
7,自定义Spring框架 7.1 spring使用回顾 自定义spring框架前,先回顾一下spring框架的使用,从而分析spring的核心,并对核心功能进行模拟. 数据访问层.定义UserDao ...
- spring框架学习(五)注解
注解Annotation,是一种类似注释的机制,在代码中添加注解可以在之后某时间使用这些信息.跟注释不同的是,注释是给我们看的,Java虚拟机不会编译,注解也是不编译的,但是我们可以通过反射机制去读取 ...
- OSGI企业应用开发(五)使用Blueprint整合Spring框架(二)
上篇文章中,我们开发了一个自定义的Bundle,接着从网络中下载到Spring和Blueprint的Bundle,然后复制到DynamicRuntime项目下. 需要注意的是,这些Bundle并不能在 ...
- 设计模式(五)——原型模式(加Spring框架源码分析)
原型模式 1 克隆羊问题 现在有一只羊 tom,姓名为: tom, 年龄为:1,颜色为:白色,请编写程序创建和 tom 羊 属性完全相同的 10 只羊. 2 传统方式解决克隆羊问题 1) 思路分析(图 ...
- 设计模式(十五)——命令模式(Spring框架的JdbcTemplate源码分析)
1 智能生活项目需求 看一个具体的需求 1) 我们买了一套智能家电,有照明灯.风扇.冰箱.洗衣机,我们只要在手机上安装 app 就可以控制对这些家电工作. 2) 这些智能家电来自不同的厂家,我们不想针 ...
- 手写Spring框架,是时候撸个AOP与Bean生命周期融合了!
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 嘎小子,这片代码水太深你把握不住! 在电视剧<楚汉传奇>中有这么一段刘邦 ...
- Spring 框架的架包分析、功能作用、优点,及jar架包简介
Spring 框架的架包详解 Spring的作用 Spring的优势 由于刚搭建完一个MVC框架,决定分享一下我搭建过程中学习到的一些东西.我觉得不管你是个初级程序员还是高级程序员抑或 ...
- spring框架详解: IOC装配Bean
1 Spring框架Bean实例化的方式: 提供了三种方式实例化Bean. 构造方法实例化:(默认无参数) 静态工厂实例化: 实例工厂实例化: 无参数构造方法的实例化: <!-- 默认情况下使用 ...
随机推荐
- hdu4998 旋转坐标系
题意: 一开始的时候有一个坐标系(正常的),然后有n个操作,每个操作是 x y d,意思是当前坐标系围绕x,y点逆时针旋转d度,最后让你输出三个数x y d,把这n个操作的最后结果,用一步 ...
- Linux提权—脏牛漏洞(CVE-2016-5195)
目录 脏牛漏洞 exp1复现: exp2复现: 脏牛漏洞 脏牛漏洞,又叫Dirty COW,存在Linux内核中已经有长达9年的时间,在2007年发布的Linux内核版本中就已经存在此漏洞.Linux ...
- 详解 WebRTC 传输安全机制:一文读懂 DTLS 协议
作者|进学 审校|泰一 DTLS (Datagram Transport Layer Security) 基于 UDP 场景下数据包可能丢失或重新排序的现实情况下,为 UDP 定制和改进的 TLS 协 ...
- Conda基本使用方法
anaconda/miniconda的安装 请点击查看我的博客 本教程全部命令操作均在CMD(win).terminal(win).终端(linux/Macos)中执行 使用前配置 因为anacond ...
- 【python】Leetcode每日一题-搜索排序数组2
[python]Leetcode每日一题-搜索排序数组2 [题目描述] 已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同. 在传递给函数之前,nums 在预先未知的某个下标 k( ...
- 初步了解web
------------------------1.Web应用程序的main方法在哪里------------------------Tomcat:从启动到运行首先,我们是通过执行 Tomcat 的s ...
- SQL Server强制使用特定索引 、并行度、锁
SQL Server强制使用特定索引 .并行度 修改或删除数据前先备份,先备份,先备份(重要事情说三遍) 很多时候你或许为了测试.或许为了规避并发给你SQL带来的一些问题,常常需要强制指定目标sql选 ...
- 在Visual Studio 中使用git——浏览版本库(七)
在Visual Studio 中使用git--什么是Git(一) 在Visual Studio 中使用git--给Visual Studio安装 git插件(二) 在Visual Studio 中使用 ...
- docker中运行envoy 报错 cannot bind '0.0.0.0:80': Permission denied
docker-compose文件 version: '3' services: envoy: image: envoyproxy/envoy-alpine:v1.15-latest volumes: ...
- [Java]数据分析--数据可视化
时间序列 需求:将一组字符顺序添加到时间序列中 实现:定义时间序列类TimeSeries,包含静态类Entry表示序列类中的各项,以及add,get,iterator,entry方法 TimeSeri ...