第五周 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. 构造方法实例化:(默认无参数) 静态工厂实例化: 实例工厂实例化: 无参数构造方法的实例化: <!-- 默认情况下使用 ...
随机推荐
- PAT 乙级 -- 1011 -- A+B和C
问题简述 给定区间[-231, 231]内的3个整数A.B和C,请判断A+B是否大于C. 输入格式: 输入第1行给出正整数T(<=10),是测试用例的个数.随后给出T组测试用例,每组占一行,顺序 ...
- Android Hook框架adbi的分析(3)---编译和inline Hook实践
本文博客地址:http://blog.csdn.net/qq1084283172/article/details/75200800 一.序言 在前面的博客中,已经分析过了Android Hook框架a ...
- SSH后门万能密码
当我们在获得一台Linux服务器的 root 权限后,我们第一想做的就是如何维持这个权限,维持权限肯定想到的就是在目标服务器留下一个后门.但是留普通后门,肯定很容易被发现.我们今天要讲的就是留一个SS ...
- web.xml常用配置详解
web.xml常用配置详解 context-param 指定 ServletContext(上下文) 配置文件路径,基本配置一般是Spring配置文件,或者是spring-security的配置文件. ...
- C++虚函数 - 静态函数能否为虚函数 .
1.virtual与静态函数 C++中,静态成员函数不能被声明为virtual函数. 例如,下面的程序会编译失败. #include<iostream> class Test { publ ...
- SprintBoot使用Validation
1.为什么要使用Validation 在开发过程中有没有使用一堆的if来判断字段是否为空.电话号码是否正确.某个输入是否符合长度等对字段的判断.这样的代码可读性差,而且还不美观,那么使用Validat ...
- Iterable 和 Iterator
可以被for循环输出的为iterable (可迭代对象) 可以被next()调用并不断返回下一个数据的对象为iterator迭代器(python一切皆对象) 数据流,无法知晓其终点,只能推过next不 ...
- [刷题] 279 Perfect Squares
要求 给出一个正整数n,寻找最少的完全平方数,使他们的和为n 示例 n = 12 12 = 4 + 4 + 4 输出:3 边界 是否可能无解 思路 贪心:12=9+1+1+1,无法得到最优解 图论:从 ...
- [前端] AJAX
背景 Asynchronous JavaScript And XML:异步js和XML,可实现异步刷新 用途 验证提交的用户名是否已存在 不使用AJAX,需要提交数据后,刷新页面来验证 使用AJAX, ...
- Docker Swarm(一)集群部署
一.机器环境 机器规划 172.16.0.89 swarm的manager节点 manager-node 172.16.0.90 swarm的node节点 node1 机器版本(均是:CentOS L ...