Spring BeanFactory和现实工厂的对比
本文不分析Spring的源码流程,只是介绍一些基础的概念,在阅读源码之前,我们应该首先明确研究的对象是什么,才能有的放矢。
Spring作为BeanFactory, 和现实工厂有着许多类似之处。
需要各种原料Class,存在各个jar包内,jar包内又分为不同的Package。
每一种原料有相应的说明书------BeanDefinition
需要存储说明书的地方 BeanDefinitionRegistry
需要搬运工:BeanFactoryPostProcessor
需要按照说明书生产零件 newInstance .
各种零件 Singleton
半成品 BeanWrapper
成品 ExposedObject
零件和零件之间有依赖关系 Dependency
需要存储零件的地方
存储半成品的地方
需要存储成品的地方
需要各种工序Processor
需要决定Processor如何执行的地方PostProcessorRegistrationDelegate,
需要有存储工序的地方
需要对零件进行组装 AutowireCapableBeanFactory, 这部分也就是注入依赖的过程。
需要对成品的一些功能进行增强。 对Method进行增强。
顺着这条线看应该会容易很多。
1: BeanDefinition 一个Class对应一个BeanDefinition,有了BeanDefinition再构建instance。
可以理解为Class可以分为不同的功能。
1.1 普通的bean
1.2 能处理@Component的bean
1.3 能处理@Configuration的bean
ConfigurationClassBeanDefinition , 对应@Configuration 修饰的Class类。 ConfigurationClassBeanDefinitionReader 是负责分析ConfigurationClass。
spring 里面有一个非常常见的变量 mbd, 意为getMergedLocalBeanDefinition 。
BeanDefinition 其实是相当复杂的一个类,需要考虑到Bean的各种可能潜在的属性以及整个生命周期。
@Nullable
private volatile Object beanClass; 代表的class
@Nullable
private String scope; 作用域
private boolean abstractFlag; 是否是abstract类
private boolean lazyInit; 是否是懒加载
private int autowireMode; autowireMode
private int dependencyCheck; 是否检查依赖
@Nullable
private String[] dependsOn; 依赖那些其他的beanClass
private boolean autowireCandidate; 候选人
private boolean primary; 是否是主类
private final Map<String, AutowireCandidateQualifier> qualifiers; 限定
@Nullable
private Supplier<?> instanceSupplier; 供应商
private boolean nonPublicAccessAllowed;
private boolean lenientConstructorResolution; 宽容的
@Nullable
private String factoryBeanName;
@Nullable
private String factoryMethodName;
@Nullable
private ConstructorArgumentValues constructorArgumentValues; 构造方法的参数
@Nullable
private MutablePropertyValues propertyValues; 属性
@Nullable
private MethodOverrides methodOverrides;
@Nullable
private String initMethodName; init方法
@Nullable
private String destroyMethodName; 销毁方法的名称
private boolean enforceInitMethod;
private boolean enforceDestroyMethod;
private boolean synthetic; 是否是人工合成的
private int role; 角色
@Nullable
private String description; 描述
@Nullable
private Resource resource; class文件的位置
@Nullable
private BeanDefinitionHolder decoratedDefinition;
@Nullable
private AnnotatedElement qualifiedElement;
boolean allowCaching = true;
boolean isFactoryMethodUnique = false;
@Nullable
volatile ResolvableType targetType;
@Nullable
volatile Class<?> resolvedTargetType; // resolvedTargetType 目标类型目标类型
@Nullable
volatile ResolvableType factoryMethodReturnType;
@Nullable
volatile Method factoryMethodToIntrospect;
final Object constructorArgumentLock = new Object();
@Nullable
Executable resolvedConstructorOrFactoryMethod;
boolean constructorArgumentsResolved = false;
@Nullable
Object[] resolvedConstructorArguments;
@Nullable
Object[] preparedConstructorArguments;
final Object postProcessingLock = new Object();
boolean postProcessed = false;
@Nullable
volatile Boolean beforeInstantiationResolved;
@Nullable
private Set<Member> externallyManagedConfigMembers;
@Nullable
private Set<String> externallyManagedInitMethods;
@Nullable
private Set<String> externallyManagedDestroyMethods;
能将事物的本质描述清楚实在是不容易。
2:既然有BeanDefinition ,那么就需要有存放BeanDefinition的地方(容器) , 称为BeanDefinitionRegistry
beanDefinitionMap 就是存放BeanDefinition的地方。 Map<String,BeanDefinition>
定义增删查等基本操作。
public interface BeanDefinitionRegistry extends AliasRegistry {
void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException; void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException; BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException; boolean containsBeanDefinition(String var1); String[] getBeanDefinitionNames(); int getBeanDefinitionCount(); boolean isBeanNameInUse(String var1);
}
除此之外还可以给BeanDefinition起一个别名。
3:Singleton
public interface SingletonBeanRegistry {
void registerSingleton(String var1, Object var2); @Nullable
Object getSingleton(String var1); boolean containsSingleton(String var1); String[] getSingletonNames(); int getSingletonCount(); Object getSingletonMutex();
}
很明显Singleton全部为Object类型,这意味着在@Autowired 注入依赖时,需要进行类型转换。 注意这里没法进行进行强制类型转换。 这也是spring推荐
使用构造方法注入依赖的原因吧, 类型擦除之后还得再还原原始类型,很复杂。
Singleton 分为两种:
3.1: 不依赖其他Singleton的Singleton
3.2: 依赖其他Singleton的Singleton
存放Singleton的地方
4: ScopedObject
存放 ScopeObject的地方
5:Bean
从功能来看: Bean分为NamedBean DisposableBean InitializingBean 和 FactoryBean<T>
6:BeanWrapper
7:存放Singleton和Scope,以及对他们进行加工改造的地方称为BeanFactory , 实际上Singleton存储在SingletonBeanRegistry ,Scope存在
RequestContextHolder 中,BeanFactory 提供了桥接入口
FactoryBean和BeanFactory 的区别, FactoryBean<T> 带有参数T , FactoryBean 只是生产T对应的BeanDefinition
FactoryBean的作用: 有些Bean能够直接通过newInstance 直接构建,有些Bean需要通过反射进行构建,比如@Mapper,@Feign ,@Repository 修饰的
interface 。这些接口需要通过FactoryBean解析,bangding相应的MethodHandler, 然后注入到BeanDefinition。 注意此时只是注册到BeanDefinition。
8:BeanInstance
9: BeanFactoryPostProcessor 这命名真让人误解
FactoryBean 不能自己注入到spring中去,需要BeanFactoryPostProcessor才能注入到spring中去。
10: BeanPostProcessor
11: InstantiationStrategy
12: proxy
13: Interceptor
下面介绍一下Processor
了解一两个Processor会对Bean的加工过程有所了解。 个人感觉这种模式和pipeline模式很像。
Processor 没法自行启动,需要委托给 PostProcessorRegistrationDelegate 进行启动。
Processor 的执行有先后顺序关系。
对于BeanFactoryPostProcessor 而言 registryProcessors > regularPostProcessors
对应BeanPostProcessor而言
priorityOrderedPostProcessors > orderedPostProcessorNames > nonOrderedPostProcessorNames > internalPostProcessors
和Aop相关的Processor
所有Processor接口的子类,
BeanFactoryProcessor接口的子类也十分多。
最后介绍一个超级大Boss DefaultListableBeanFactory
整个BeanFactory的继承体系也十分庞大。
spring 最终注入依赖的地方
InjectionMetadata
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs) throws Throwable {
if (this.isField) {
Field field = (Field)this.member;
ReflectionUtils.makeAccessible(field);
field.set(target, this.getResourceToInject(target, requestingBeanName));
} else {
if (this.checkPropertySkipping(pvs)) {
return;
} try {
Method method = (Method)this.member;
ReflectionUtils.makeAccessible(method);
method.invoke(target, this.getResourceToInject(target, requestingBeanName));
} catch (InvocationTargetException var5) {
throw var5.getTargetException();
}
}
}
程序架构设计应该不只是顺序思维,更应该锻炼立体思维,思前顾后,承上启下,注重接口和继承体系的设计,还应该掌握一些基础基本的专业术语,设计模式。
你应该明确自己研究的对象,怎么描述它,怎么构建它,怎么增强它,怎么存储它,以及怎么使用它。
与AOP相关的概念
Advide 。
Advisor
Spring BeanFactory和现实工厂的对比的更多相关文章
- Spring - BeanFactory 新旧工厂差异
在将要被加入到spring容器中的service中,添加static静态代码块(加载类时被调用),用于判断spring中新旧bean工厂的加载性质. package com.witwicky.serv ...
- spring BeanFactory及ApplicationContext中Bean的生命周期
spring bean 的生命周期 spring BeanFactory及ApplicationContext在读取配置文件后.实例化bean前后.设置bean的属性前后这些点都可以通过实现接口添加我 ...
- Spring BeanFactory与FactoryBean的区别及其各自的详细介绍于用法
Spring BeanFactory与FactoryBean的区别及其各自的详细介绍于用法 1. BeanFactory BeanFactory,以Factory结尾,表示它是一个工厂类(接口),用于 ...
- Spring BeanFactory 与 FactoryBean 的区别
BeanFactory 和 FactoryBean 都是Spring Beans模块下的接口 BeanFactory是spring简单工厂模式的接口类,spring IOC特性核心类,提供从工厂类中获 ...
- Spring中如何使用工厂模式实现程序解耦?
目录 1. 啥是耦合.解耦? 2. jdbc程序进行解耦 3.传统dao.service.controller的程序耦合性 4.使用工厂模式实现解耦 5.工厂模式改进 6.结语 @ 1. 啥是耦合.解 ...
- Spring 源码(3)Spring BeanFactory 是怎么创建的?
Spring创建 BeanFactory 的方式 按照Bean的配置方式手动创建可以分为两种: 使用XMl配置的Bean 这种方式使用xml配置文件配置Bean的信息并且设置扫描的路径,扫描到的包可以 ...
- XI.spring的点点滴滴--IObjectFactoryPostProcessor(工厂后处理器)
承接上文 IObjectFactoryPostProcessor(工厂后处理器)) 前提是实现接口的对象注册给当前容器 直接继承的对象调用这个postProcessBeanFactory方法,参数为工 ...
- Spring BeanFactory实例化Bean的详细过程
Spring中Bean的实例化是Bean生命周期的一个重要环节,通常Bean初始化后将不再改变. 那么Spring实例Bean的过程到底是怎么样的呢?! 要想获取到一个bean对象,得先通过Bea ...
- windows服务 MVC之@Html.Raw()用法 文件流的读写 简单工厂和工厂模式对比
windows服务 public partial class Service1 : ServiceBase{ System.Threading.Timer recordTimer;public S ...
随机推荐
- GO语言基础---值传递与引用传递
package main import ( "fmt" ) /* 值传递 函数的[形式参数]是对[实际参数]的值拷贝 所有对地址中内容的修改都与外界的实际参数无关 所有基本数据类型 ...
- TVM部署预定义模型
TVM部署预定义模型 本文通过深度学习框架量化的模型加载到TVM中.预量化的模型导入是在TVM中提供的量化支持之一. 本文演示如何加载和运行由PyTorch,MXNet和TFLite量化的模型.加载后 ...
- H.264/H265码流解析
H.264/H265码流解析 一.H.264码流解析 一个原始的H.264 NALU 单元常由 [StartCode] [NALU Header] [NALU Payload] 三部分组成 一个原始的 ...
- TensorFlow分布式详解
每次 TensorFlow 运算都被描述成计算图的形式,允许结构和运算操作配置所具备的自由度能够被分配到各个分布式节点上.计算图可以分成多个子图,分配给服务器集群中的不同节点. 强烈推荐读者阅读论文& ...
- C ++基本输入/输出
C ++基本输入/输出 本文将学习如何使用cin对象从用户那里获取输入,并使用cout对象在示例的帮助下向用户显示输出. C ++输出 在C ++中,cout将格式化的输出发送到标准输出设备,例如屏幕 ...
- Redis6.x学习笔记(五)哨兵
前言 最近学习Redis6.x,特做笔记以备忘,与大家共学.课程是从私塾在线下载的,他们把架构师课程都放出来了,大家可以去下载学习,不要钱的,地址是http://t.hk.uy/eK7,课程很不错,值 ...
- 基于 Spring Security 的前后端分离的权限控制系统
话不多说,入正题.一个简单的权限控制系统需要考虑的问题如下: 权限如何加载 权限匹配规则 登录 1. 引入maven依赖 1 <?xml version="1.0" enc ...
- 自动删除n天前的日志(此处用于业务删除xml文件)
Linux应用总结:自动删除n天前的日志 linux是一个很能自动产生文件的系统,日志.邮件.备份等.虽然现在硬盘廉价,我们可以有很多硬盘空间供这些文件浪费,让系统定时清理一些不需要的文件很有一种爽快 ...
- Java安全之Fastjson内网利用
Java安全之Fastjson内网利用 0x00 前言 在打Fastjson的时候,基本上都是使用JNDI注入的方式去打,也就是 JdbcRowSetImpl 链分析的链去打,但是遇到一些不出网的情况 ...
- Duilib的双缓冲实现,附带GDI、WTL的双缓冲实现
前言: 闪烁问题,之前的经验是使用双缓冲,借此机会,把双缓冲的研究心得总结下. 双缓冲的含义: 缓冲这个词,相信大家都不陌生,Cache.主要是为了解决上下游(或者模块.或者系统)等性能不匹配问题.如 ...