1、Spring IOC
tips:由于Markdowm上传图片过多,所以出现频繁上传有些显示不出来,如果有需要可联系我,抱歉!!
Spring IOC 概述?
提到 IOC,初次接触的人可能会觉得非常高大上,觉得是一种很高深的技术,然而事实呢?事实是 IOC 其实仅仅只是一个 Map 集合而已。
IOC 全称为:Inversion of Control。控制反转的基本概念是:不用创建对象,但是需要描述创建对象的方式。
简单的说我们本来在代码中创建一个对象是通过 new 关键字,而使用了 Spring 之后,我们不在需要自己去 new 一个对象了,而是直接通过容器里面去取出来,再将其自动注入到我们需要的对象之中,即:依赖注入。
也就说创建对象的控制权不在我们程序员手上了,全部交由 Spring 容器进行管理,程序要只需要注入就可以了,所以才称之为控制反转。
实际上,IOC 也被称之为 IOC 容器,那么既然是一个容器,肯定是要用来放东西的,那么 IOC 容器用来存储什么呢?如果大家对 Spring 有所了解的话,那就知道在 Spring 里面可以说是一切面向 Bean 编程,而 Bean 指的就是我们交给 Spring 管理的对象,今天我们要学习的 IOC 容器就是用来存储所有 Bean 的一个容器。
:::info
Spring IOC 三大核心接口?
:::
BeanDefinition:定义了一个** Bean 相关配置文件的各种信息,比如当前 Bean 的构造器参数,属性,以及其他一些信息,这个接口同样也会衍生出其他一些实现类,如
BeanDefinitionReader:定义了一些读取配置文件**的方法,支持使用 Resource 和 String 位置参数指定加载方法,具体的时候可以扩展自己的特有方法。该类只是提供了一个建议标准,不要求所有的解析都实现这个接口。
BeanFactory:访问 Bean 容器的顶层接口,我们最常用的 ApplicationContext 接口也实现了 BeanFactory。
1.1、Spring 框架流程
1.1.1、Spring 基本启动流程
- @SpringBootApplication 注解启动自动装配
- SpringApplication.run() 创建SpringApplication 实例来调用 run() 方法 返回一个ConfigurableApplicationContext 接口
/**
* Static helper that can be used to run a {@link SpringApplication} from the
* specified sources using default settings and user supplied arguments.
*
* @param primarySources the primary sources to load
* @param args the application arguments (usually passed from a Java main method)
* @return the running {@link ApplicationContext}
*/
public static ConfigurableApplicationContext run(Class<?>[] primarySources,
String[] args) {
return new SpringApplication(primarySources).run(args);
}
1.1.1.1、ConfigurableApplicationContext 接口
:::info
那么 ConfigurableApplicationContext 接口作用是什么呢?
:::
设置上下文 ID,设置父应用上下文,添加监听器,刷新容器,关闭,判断是否活跃等方法。
是SpringBoot最核心的内容-应用容器,run方法内部也基本都是针对它进行的各种初始化操作,运行完成后返回的也是它的实例,下面我们就梳理下它的属性和方法,对它做一个简单的了解。
- setId:设置应用容器的唯一id
- setParent:设置父级容器(上下文)
- setEnvironment:设置当前容器环境变量
- getEnvironment:返回此应用程序上下文的环境,允许进一步自定义
- addBeanFactoryPostProcessor:添加BeanFactoryPostProcessor,BeanFactoryPostProcessor功能比较强大,它可以修改容器的内部bean factory,改变bean的创建
- addApplicationListener:添加容器监听器,主要是指继承了ApplicationListener的监听器
- setClassLoader:设置类加载器
- addProtocolResolver:注册协议解析器。协议解析器的作用就是根据指定的地址和资源加载期,解析资源并将资源返回
- refresh:加载或者刷新配置持久化代理,它的来源可以是java基础配置、 xml文件、属性文件、数据库或者其他文件格式。根据官方文档描述,refresh是一个启动方法,如果执行失败,它会销毁已经创建的单例,以避免悬空资源。也就是说,在调用这个方法之后,要么全部实例化,要么根本不实例化。
- registerShutdownHook:注册关闭钩子函数
- close:关闭容器
- isActive:获取容器是否活跃
- getBeanFactory:获取bean factory
该接口的核心方法包括设置当前容器环境变量、添加BeanFactory后置处理器、添加容器监听器、加载或者刷新配置持久化代理。
ConfigurableApplicationContext是ApplicationContext的子类,该接口的主要任务就是配置应用程序上下文功能。
:::info
那 ConfigurableApplicationContext 的父类是谁?
:::
ApplicationContext 接口是所有上下文接口中的基类,自然ConfigurableApplicationContext的父类就是ApplicationContext 接口。
1.1.1.2、ApplicationContext 接口
Spring容器最基本的接口就是BeanFactory。BeanFactory负责配置、创建、管理Bean;
ApplicationContext由BeanFactory派生而来;BeanFactory的许多功能需要编程实现,而在ApplicationContext中则可以通过配置的方式实现;
ApplicationContext因此也称之为Spring上下文。Spring容器负责管理Bean与Bean之间的依赖关系。
- 从ListableBeanFactory接口继承来的:用于访问应用组件的工厂方法
- 从ResourceLoader接口继承来的:用通用的方式加载文件资源
- 从ApplicationEventPublisher接口继承来的:注册和发布事件
- 从MessageSource接口继承来的:处理消息,支持国际化
如果说BeanFactory是Spring的心脏,那么ApplicationContext就是完整的身躯了。
ApplicationContext由BeanFactory派生而来,提供了更多面向实际应用的功能。
而ConfigurableApplicationContext作为实现ApplicationContext 的核心接口。
ConfigurableApplicationContext 接口中核心实现方法就是 refresh() 方法实现加载或者刷新配置持久化代理,子类抽象类通过实现该上下文接口来实现 refresh() 方法实现刷新或者加载对象。
1.1.2、refresh() 方法核心流程
1.1.2.1、AbstractApplicationContext 类
首先我们需要说一个这个抽象类的作用:这个类使用到了模板设计模式,定义了refresh()方法调用方法的顺序,但是这些被调用的某些方法是被其子类实现的。并且AbstractApplicationContext也使用了组合的模式,它对BeanFactory的操作都是委托给DefaultListableBeanFactory实现的,而不是在自身去实现这么多的逻辑。
:::info
基本介绍
:::
- 它是对ApplicationContext接口的抽象实现,不强制指定用于配置的存储类型(就是注解或者xml文件配置等的类型),只实现公共上下文功能。
- 它使用了模板设计模式,需要具体的子类去实现抽象方法
- 与纯BeanFactory不同,ApplicationContext用于检测在其内部bean工厂中定义的特殊bean:因此,他会自动注册在context中定义为bean的BeanFactoryPostProcessors、BeanPostProcessors和ApplicationListeners。
- 在context中MessageSource也可能作为bean被提供,其名字为"messageSource",否则,消息解析将会被委托给父类上下文。此外,在context中,对应用程序事件的广播由ApplicationEventMulticaster类型的"applicationEventMulticaster"的bean提供,否则,默认会使用SimpleApplicationEventMulticaster。
- 通过继承DefaultResourceLoader实现了资源的加载功能,主要作用:将非URL资源路径视为类路径资源(支持包含包路径的完整类路径资源名称),除非在子类重写getResourceByPath方法。
定义了refresh()方法调用方法的顺序,作为一个抽象类同时使用模板方法使用抽象方法将实现给子类来实现。
AbstractApplicationContext 的子类实现,一类是GenericApplicationContext的子类,一类是AbstractRefreshableApplicationContext的子类.
在refreshBeanFactory阶段AbstractRefreshableApplicationContext体系的ApplicationContext会返回一个新的BeanFactory,并重新加载bean。所以AbstractRefreshableApplicationContext使用的比较多。
AbstractApplicationContext 的实现流程。
1.1.2.2、AbstractRefreshableApplicationContext 抽象类
:::info
主要作用:获取了 DefaultListableBeanFactory 的实例化以及对资源配置的加载操作
:::
AbstractRefreshableApplicationContext 抽象类是热刷新功能,它内部也持有一个DefaultListableBeanFactory实例, 每次刷新refresh ()时都会销毁当前的BeanFactory实例并重新创建DefaultListableBeanFactory实例 。
该类的主要方法:
作用:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nTKOYNo8-1690811375696)(https://cdn.nlark.com/yuque/0/2023/png/25484710/1679757499394-343ecfde-5b45-4455-a0b6-3a4a103872e5.png#averageHue=%23f9f9f7&clientId=u0e3eeaa2-764b-4&from=paste&height=453&id=ud14b8d87&originHeight=693&originWidth=1519&originalType=binary&ratio=1.5&rotation=0&showTitle=false&size=286563&status=done&style=none&taskId=u2aca84c3-5edd-40ec-a8d3-41a662cff43&title=&width=994)]
AbstractRefreshableApplicationContext 的实现类 AbstractXmlApplicationContext
将配置路径传入到 **XMLBeanDefinitionReader **类中解析规定的格式文档生成BeanDefinition对象
总结流程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cHcbP6dU-1690811375697)(https://cdn.nlark.com/yuque/0/2022/png/25484710/1659349331714-93219e9d-d5d3-48cc-b495-0945cb7bfafd.png?x-oss-process=image%2Fresize%2Cw_1125%2Climit_0#averageHue=%23faf9f7&from=url&height=611&id=tunIb&originHeight=620&originWidth=1125&originalType=binary&ratio=1.5&rotation=0&showTitle=false&status=done&style=none&title=&width=1108)]
1.1.2.3、BeanFactory 默认实现类
:::info
DefaultListableBeanFactory 作为BeanFactory的默认实现抽象类,基于BeanDefinition对象,负责Bean注册后的处理。就是一个容器接口,可以独立使用的类。
:::
那么这里存在一个BeanFactory的默认实现类来进行对BeanDefinition对象的注册,那必定会有需要注册的地方?
1.1.2.4、解析Bean对象(XMLBeanDefinitionReader)
:::info
XMLBeanDefinitionReader 对象来实现解析xml配置文件
:::
通过XMLBeanDefinitionReader来读取资源
doLoadBeanDefinitions方法也是通过遍历标签中的参数进行解析数据来存储到BeanDefinition对象中并且注入到DefaultListableBeanFactory & beanDefinitionMap中。
注册完BeanDefinition对象就结束了?当然没有,还需要对该对象进行扩展功能。
由于 ApplicationContext 的获取并不能直接在创建 Bean 时候就可以拿到,所以需要在 refresh 操作时,把 ApplicationContext 写入到一个包装的 BeanPostProcessor 中去,再由 AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization 方法调用。
让继承自 ApplicationContextAware 的 Bean 对象都能感知所属的 ApplicationContext。
:::info
由于Bean初始化前后会回调BeanPostProcessor中定义的2个方法,一个postProcessBeforeInitialization和postProcessAfterInitialization方法,不能直接将ApplicationContext存储在BeanDefinition中,所以将ApplicationContext包装成ApplicationContextAwareProcessor对象,初始化前调用ApplicationContextAwareProcessor.postProcessBeforeInitialization方法设置setApplicationContext
:::
下面是添加BeanFactory的后置处理器和BeanDefinition的后置处理器调用回调方法来设置属性值。
实例化前需要先执行BeanFactoryPostProcessor类可以实现提供修改 BeanDefinition 属性的机制。
需要先注册后置处理器
1.1.2.5、AbstractBeanFactory
:::info
作用:名管理,单例创建与注册,工厂方法FactoryBean支持,
:::
子类实现getBeanDefinition()方法和createBean方法
1.1.2.6、实例化、填充属性、初始化
:::info
Bean对象的实例化
:::
使用策略模式来实现JDK 、CGLIB选择不同动态代理策略实现
那使用普通的JavaBean对象不行?为什么一定需要使用代理对象?
我们扩充了 Bean 容器的功能,把实例化对象交给容器来统一处理,但在我们实例化对象的代码里并没有考虑对象类是否含构造函数,也就是说如果我们去实例化一个含有构造函数的对象那么就要抛异常了。
如果没有使用代理模式的话,实例化对象是没有考虑到构造函数的入参,就会出现报错,就需要动态代理来解决含参构造的实例化。
:::info
填充属性
:::
:::info
初始化对象和后置处理器
:::
执行AbstractAutowireCapableBeanFactory #initializeBean方法
- 前置处理方法
- 初始化方法
对该Bean进行了初始化后再调用后置处理方法
- 后置处理方法
在上面的前置处理方法同一个类中实现
1.1.2.7、销毁方法
哪里用到了销毁方法?怎么使用销毁方法?
需要满足用户可以在 xml 中配置初始化和销毁的方法,也可以通过实现类的方式处理,比如我们在使用 Spring 时用到的 DisposableBean 两个接口。
:::info
哪里用到了销毁方法?
:::
所以在创建Bean对象之后就需要安装当前实例模式和校验是否配置了销毁方法来注册销毁适配器。
:::info
怎么实现销毁方法?
:::
实现接口 DisposableBean、配置信息 destroy-method
- 在创建 Bean 对象的实例的时候,需要把销毁方法保存起来,方便后续执行销毁动作进行调用。
- 那么这个销毁方法的具体方法信息,会被注册到 DefaultSingletonBeanRegistry 中新增加的 Map<String, DisposableBean> disposableBeans 属性中去,因为这个接口的方法最终可以被类 AbstractApplicationContext 的 close 方法通过 getBeanFactory().destroySingletons() 调用。
- 在注册销毁方法的时候,会根据是接口类型和配置类型统一交给 DisposableBeanAdapter 销毁适配器类来做统一处理。实现了某个接口的类可以被 instanceof 判断或者强转后调用接口方法
1.1.3、Aware 是什么作用?
我们学习过程中一般会看见一个未知的事物都会问:这个是什么东西?有什么用?怎么设计?哪里使用?怎么用?
:::info
什么是Aware?
:::
在refresh方法中实例化后–> Aware 处理 --> 初始化前置处理器 之间需要对所有Bean需要感知Spring容器的对象都需要实现Aware方法作为一个标识符。
在实际项目中,我们不可避免的要用到 Spring 容器本身提供的资源(难免要有事情需要少先队组织的帮助),这时候要让 Bean 主动意识到 Spring 容器的存在,才能调用 Spring 所提供的资源,这就是 Spring Aware. 其实 Spring Aware 是 Spring 设计为框架内部使用的,若使用了,你的 Bean 将会和 Spring 框架耦合,所以自己不单独使用,但是在读框架源码时希望你不再模糊。
:::info
有什么用?
:::
通常使用 Spring Aware 的目的是为了让 Bean 获得 Spring 容器的服务。
bean实现个某某Aware接口,然后这个bean就可以通过实现接口的方法,来接收接口方法传递过来的资源。
用Aware机制对Bean实现方法回调进行扩展。在Spring中ApplicationContextAware定义了setApplicationContext方法,并在ApplicationContextAwareProcessor中对其实现类进行回调,完成对bean设置上下文的功能。我们也可以自定义Aware和BeanPostProcessor回调方法,进行扩展。
重点在于:通过实现了Aware接口我们就可以通过**instanceof **来判断是否需要感知该类,在ApplicationContextAwareProcessor中对Aware实现类中进行回调方法进行操作;
举例:
:::info
前面的ApplicationContext类中为什么需要使用ApplicationContextAware的原因就是,如果没有实现Aware 接口就不能对当前Bean对象进行判断是否需要注入ApplicationContext对象,如果实现了Aware接口就可知当前ApplicationContextAware类是需要进行操作,在ApplicationContextAwareProcessor.postProcessBeforeInitialization 方法中就调用回调方法setApplicationContext()方法来进行注册Aware。这就是为什么需要实现接口Aware(这个接口就是一个识别作用和ArrayList集合中的RandomAccess接口是一样的作用)
:::
:::info
怎么设计?
:::
实现Aware接口标识当前接口可以感知Spring容器
- 实现此接口,既能感知到所属的 ApplicationContext
如果Bean实现了ApplicationContextAware接口说明该Bean可以使用到ApplicationContext对象
- 添加 ApplicationContextAwareProcessor,让继承自 ApplicationContextAware 的 Bean 对象都能感知所属的 ApplicationContext。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mOsqWv9q-1690811375703)(https://cdn.nlark.com/yuque/0/2023/png/25484710/1679822436313-e7fecd14-5bc8-4685-bdef-c8c908cc9ae4.png#averageHue=%23f8f7f6&clientId=u2a79aa7b-398c-4&from=paste&height=341&id=u444c3fbd&originHeight=512&originWidth=1369&originalType=binary&ratio=1.5&rotation=0&showTitle=false&size=175982&status=done&style=none&taskId=uf4e9a00e-6eda-477c-a63d-4e175da2f19&title=&width=912.6666666666666)]
:::info
如何使用?
:::
那是怎么通知实现类Aware实现接口的类呢?
通过回调方法,如果某些类实现了具体的XxxAware接口就会调用他们的实现类的方法进行操作。
例如:
这里的BeanFactoryAware,那实现了BeanFactoryAware的类有哪些?
如果哪里出现了依赖某个对象,然后需要实现Aware的某个接口就可以进行回调方法进行对象参数赋值。
比如上面的AbstractApplicationEventMulticaster抽象类中的BeanFactory接口中聚合了该接口,那我们要如何设置参数,就可以将BeanFactoryAware实现Aware接口,然后AbstractApplicationEventMulticaster实现BeanFactoryAware接口,就实现回调方法,之后然后某个Bean对象实现了该BeanFactoryAware就会进行调用回调方法进行赋值。
:::info
使用场所
:::
每一个BeanFactory会注册一系列的PostProcessor对象
然后循环加载所有的Bean同时调用Bean的后置处理器PostProcessorBeforeInitialization方法。
所以在初始化之前,会给容器属性赋值执行实现了Aware接口的方法。
1.1.4、对象作用域
- 整个的实现过程包括了两部分,一个解决单例还是原型对象,另外一个处理 FactoryBean 类型对象创建过程中关于获取具体调用对象的 getObject 操作。
- SCOPE_SINGLETON、SCOPE_PROTOTYPE,对象类型的创建获取方式,主要区分在于 AbstractAutowireCapableBeanFactory#createBean 创建完成对象后是否放入到内存中,如果不放入则每次获取都会重新创建。
- createBean 执行对象创建、属性填充、依赖加载、前置后置处理、初始化等操作后,就要开始做执行判断整个对象是否是一个 FactoryBean 对象,如果是这样的对象,就需要再继续执行获取 FactoryBean 具体对象中的 getObject 对象了。整个 getBean 过程中都会新增一个单例类型的判断factory.isSingleton(),用于决定是否使用内存存放对象信息。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9c912ek3-1690811375705)(https://cdn.nlark.com/yuque/0/2023/png/25484710/1679825296688-f8570ac8-b732-4887-a4c9-051266810f96.png#averageHue=%23fcfbfa&clientId=u2a79aa7b-398c-4&from=paste&height=643&id=u46694300&originHeight=964&originWidth=1165&originalType=binary&ratio=1.5&rotation=0&showTitle=false&size=134084&status=done&style=none&taskId=u23bd84ea-7601-4fc3-a9be-fb92c738e89&title=&width=776.6666666666666)]
XmlBeanDefinitionReader 会解析到配置的单例还是原型模式进行配置
createBean时需要判断是单例还原型
1.1.5、容器事件和事件监听
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gZOwRh4r-1690811375706)(https://cdn.nlark.com/yuque/0/2023/png/25484710/1679826039180-0647800a-cac8-42ee-9877-1a5d5b8f3ee2.png#averageHue=%23f3e8e3&clientId=u2a79aa7b-398c-4&from=paste&height=756&id=u98bffb57&originHeight=1134&originWidth=1541&originalType=binary&ratio=1.5&rotation=0&showTitle=false&size=105906&status=done&style=none&taskId=ub3aa5d60-3190-4409-a7e3-4691b7b1ff7&title=&width=1027.3333333333333)]
- 在整个功能实现过程中,仍然需要在面向用户的应用上下文 AbstractApplicationContext 中添加相关事件内容,包括:初始化事件发布者、注册事件监听器、发布容器刷新完成事件。
- 使用观察者模式定义事件类、监听类、发布类,同时还需要完成一个广播器的功能,接收到事件推送时进行分析处理符合监听事件接受者感兴趣的事件,也就是使用 isAssignableFrom 进行判断。
- isAssignableFrom 和 instanceof 相似,不过 isAssignableFrom 是用来判断子类和父类的关系的,或者接口的实现类和接口的关系的,默认所有的类的终极父类都是Object。如果A.isAssignableFrom(B)结果是true,证明B可以转换成为A,也就是A可以由B转换而来。
:::info
AbstractApplicationContext#refresh 中添加事件处理操作
:::
:::info
初始化事件发布者
:::
:::info
那怎么使用这个事件监听器?
:::
需要先进行注册监听器
:::info
发布事件
:::
实现ApplicationEventListener接口
1.1.6、SpringIOC流程图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9zLHnrol-1690811375708)(https://cdn.nlark.com/yuque/0/2023/png/25484710/1679820496111-f4d08b21-9b4b-4126-b0e0-15b9fe29c395.png#averageHue=%23fefcfc&clientId=u2a79aa7b-398c-4&from=paste&id=ufa553cc8&originHeight=2222&originWidth=1894&originalType=url&ratio=1.5&rotation=0&showTitle=false&size=297115&status=done&style=none&taskId=u3b31cd8d-66f0-4e1d-b24c-10c16bf34c5&title=)]
1.2、实现SpringIOC容器
1.2.1、创建容器、Bean的定义、注入、获取
:::info
Spring Bean 容器是什么?
:::
Spring 包含并管理应用对象的配置和生命周期,在这个意义上它是一种用于承载对象的容器,你可以配置你的每个 Bean 对象是如何被创建的,这些 Bean 可以创建一个单独的实例或者每次需要时都生成一个新的实例,以及它们是如何相互关联构建和使用的。
如果一个 Bean 对象交给 Spring 容器管理,那么这个 Bean 对象就应该以类似零件的方式被拆解后存放到 Bean 的定义中,这样相当于一种把对象解耦的操作,可以由 Spring 更加容易的管理,就像处理循环依赖等操作。
当一个 Bean 对象被定义存放以后,再由 Spring 统一进行装配,这个过程包括 Bean 的初始化、属性填充等,最终我们就可以完整的使用一个 Bean 实例化后的对象了。
设计一个简单的Spring 容器需要以下几步:定义、存放、获取Bean 对象
那么一般我们实现容器都会使用索引式 的数据结构哪个加快索引速率,选择HashMap是最合适不过了。
- 定义:**BeanDefinition **包括 singleton、prototype、BeanClassName 等。但是spring源码的BeanDefinition是作为接口来提供通用的规范由子类来实现,不同的子类实现方法。
- 注册:这个过程就相当于我们把数据存放到 HashMap 中,只不过现在 HashMap 存放的是定义了的 Bean 的对象信息。
- 获取:最后就是获取对象,Bean 的名字就是 key,Spring 容器初始化好 Bean 以后,就可以直接获取了。
实现的类:
-
BeanDefinition:用于保存 Bean 的相关信息,包括属性、构造方法参数、依赖的 Bean 名称及是否单例、延迟加载等,它是实例化 Bean 的原材料,Spring 就是根据 BeanDefinition 中的信息实例化 Bean。
-
BeanFactory:作为IOC容器的顶层核心接口,主要职责:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖
:::info
怎么实现Bean的定义、注入、获取?
:::
实现 Bean 容器关于 Bean 对象的注册和获取。将 Bean 的创建交给容器,实现控制反转,不需要传入一个实例化好的 Bean 对象,是否为单列对象,如果为单例对象则需要从内存中获取对象的。
Bean 注册的时候只注册一个类信息,而不会直接把实例化信息注册到 Spring 容器中。
下面是需要实现的类: -
BeanFactory:提供 Bean 的获取方法 getBean(String name)。
-
AbstractBeanFactory :Bean 工厂接口由抽象类 AbstractBeanFactory 实现。这样使用模板模式的设计方式,可以统一收口通用核心方法的调用逻辑和标准定义,也就很好的控制了后续的实现者不用关心调用逻辑,按照统一方式执行。那么类的继承者只需要关心具体方法的逻辑实现即可。(模板方法模式)
-
AbstractAutowireCapableBeanFactory:继承抽象类AbstractBeanFactory实现相应的抽象方法,但是AbstractAutowireCapableBeanFactory 本身也是一个抽象类,所以它只会实现属于自己的抽象方法,其他抽象方法由继承 AbstractAutowireCapableBeanFactory 的类实现。这里就体现了类实现过程中的各司其职。
-
SingletonBeanRegistry :单例接口定义(单例注册表),规范单例的接口实现方法。
-
DefaultSingletonBeanRegistry :默认的单例注册实现类,实现单例接口中规范的方法,获取单例的Bean对象等信息。之后会被抽象类AbstractBeanFactory 工厂继承。
-
**DefaultListableBeanFactory:**默认实现了ListableBeanFactory和BeanDefinitionRegistry接口,基于BeanDefinition对象,是一个成熟的bean Factroy。就是作为一个独立存在的容器来存储Bean对象的一个类,在访问bean前,需要注册所有的definition(可能从bean definition配置文件中)。使用预先建立的bean定义元数据对象,从本地的BeanDefinition表中查询BeanDefinition因而将不会花费太多成本。
-
**BeanDefinitionRegistry:**该类的作用主要是向注册表中注册 BeanDefinition 实例,完成 注册的过程。定义了关于 BeanDefinition 的注册、移除、查询等一系列的操作。
-
BeansException:统一的Bean对象运行时异常类。
1.2.1.1、工程结构
spring—framework
├─src
│ ├─main
│ │ ├─java
│ │ │ └─cn
│ │ │ └─wen
│ │ │ └─springframework
│ │ │ ├─beans
│ │ │ │ │
│ │ │ │ └─factory
│ │ │ │ │ BeanFactory.java
│ │ │ │ │
│ │ │ │ ├─config
│ │ │ │ │ BeanDefinition.java
│ │ │ │ │ SingletonBeanRegistry.java
│ │ │ │ │
│ │ │ │ └─support
│ │ │ │ AbstractAutowireCapableBeanFactory.java
│ │ │ │ AbstractBeanFactory.java
│ │ │ │ BeanDefinitionRegistry.java
│ │ │ │ DefaultListableBeanFactory.java
│ │ │ │ DefaultSingletonBeanRegistry.java
│ │ │ │
│ │
│ └─test
│ └─java
│ └─cn
│ └─wen
│ └─springframework
│ └─test
│ │ ApiTest.java
│ │
│ └─bean
│ UserService.java
- BeanFactory 的定义由 AbstractBeanFactory 抽象类实现接口的 getBean 方法
- 而 AbstractBeanFactory 又继承了实现了 SingletonBeanRegistry 的DefaultSingletonBeanRegistry 类。这样** AbstractBeanFactory 抽象类就具备了单例 Bean 的注册功能**。
- AbstractBeanFactory 中又定义了两个抽象方法:getBeanDefinition(String beanName)、createBean(String beanName, BeanDefinition beanDefinition) ,而这两个抽象方法分别由 DefaultListableBeanFactory、AbstractAutowireCapableBeanFactory 实现。
- 最终 DefaultListableBeanFactory 还会继承抽象类 AbstractAutowireCapableBeanFactory 也就可以调用抽象类中的 createBean 方法了。
1.2.1.2、BeanDefinition 定义
cn.wen.springframework.beans.factory.config.BeanDefinition
/**
* @ClassName: BeanDefinition
* @Author: 小飞
* @Date: 2023/3/25 21:06
* @Description: 用于保存Bean的相关信息,包括属性、构造方法参数、
* 依赖的Bean名称及是否单例、延迟加载等,它是实例化 Bean 的原材料,存储Bean初始化时的元数据
* Spring就是根据BeanDefinition中的信息实例化 Bean。
*/
public class BeanDefinition {
// scope类型:单例类型
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
// scope类型:原型类型
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
// 当前bean对象的class类型
private Class beanClass;
// 初始化方法名称
private String initMethodName;
// 销毁方法名称
private String destroyMethodName;
// scope类型默认类型:单例类型
private String scope = SCOPE_SINGLETON;
private boolean singleton = true;
private boolean prototype = false;
public BeanDefinition(Class beanClass) {
this.beanClass = beanClass;
}
public void setScope(String scope) {
this.scope = scope;
this.singleton = SCOPE_SINGLETON.equals(scope);
this.prototype = SCOPE_PROTOTYPE.equals(scope);
}
public boolean isSingleton() {
return singleton;
}
public boolean isPrototype() {
return prototype;
}
public Class getBeanClass() {
return beanClass;
}
public void setBeanClass(Class beanClass) {
this.beanClass = beanClass;
}
public String getInitMethodName() {
return initMethodName;
}
public void setInitMethodName(String initMethodName) {
this.initMethodName = initMethodName;
}
public String getDestroyMethodName() {
return destroyMethodName;
}
public void setDestroyMethodName(String destroyMethodName) {
this.destroyMethodName = destroyMethodName;
}
}
:::info
同时需要提供 BeanDefinition 的接口来规范实现类的实现方法。
:::
cn.wen.springframework.beans.factory.support.BeanDefinitionRegistry
/**
* @ClassName: BeanDefinitionRegistry
* @Author: 小飞
* @Date: 2023/3/26 22:39
* @Description: BeanDefinition 的注册接口
*/
public interface BeanDefinitionRegistry {
/**
* 向注册表中注册 BeanDefinition
* @param beanName
* @param beanDefinition
*/
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
}
1.2.1.3、单例注册接口定义和实现
cn.wen.springframework.beans.factory.config.SingletonBeanRegistry
/**
* @ClassName: SingletonBeanRegistry
* @Author: 小飞
* @Date: 2023/3/25 21:21
* @Description: 单例注册表
*/
public interface SingletonBeanRegistry {
/**
* 通过 beanName 获取单例 Bean 对象
* @param beanName
* @return
*/
Object getSingleton(String beanName);
/**
* 传入 beanName 和 单例对象注册到单例池中
* @param beanName
* @param singletonObject
*/
void registerSingleton(String beanName, Object singletonObject);
}
- 这个类比较简单主要是定义了一个获取单例对象的接口
- 定义了一个注册单例对象的接口
单例接口的默认实现类
cn.wen.springframework.beans.factory.support.DefaultSingletonBeanRegistry
/**
* @ClassName: DefaultSingletonBeanRegistry
* @Author: 小飞
* @Date: 2023/3/26 22:37
* @Description: 默认的单例注册实现类,实现单例接口中规范的方法,获取单例的Bean对象等信息。
* 之后会被抽象类AbstractBeanFactory 工厂继承。
*/
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {
private final Map<String, Object> singletonObjects = new HashMap<>();
@Override
public Object getSingleton(String beanName) {
return singletonObjects.get(beanName);
}
@Override
public void registerSingleton(String beanName, Object singletonObject) {
}
protected void addSingleton(String beanName, Object singletonObject) {
singletonObjects.put(beanName, singletonObject);
}
}
- 在 DefaultSingletonBeanRegistry 中主要实现 getSingleton 方法,同时实现了一个受保护的 addSingleton 方法,这个方法可以被继承此类的其他类调用。包括:AbstractBeanFactory 以及继承的 DefaultListableBeanFactory 调用,因为AbstractBeanFactory 抽象类需要实现创建单例对象的实现方法。
1.2.1.4、抽象类定义模板方法(AbstractBeanFactory)
:::info
BeanFactory是实现IOC容器的核心接口,通过beanName或者beanName+参数获取指定的Bean对象
它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
:::
那么就需要一个BeanFactory 接口来规范对应的方法。
cn.wen.springframework.beans.factory.BeanFactory
/**
* @ClassName: BeanFactory
* @Author: 小飞
* @Date: 2023/3/25 21:24
* @Description: BeanFactory是实现IOC容器的核心接口,通过beanName或者beanName+参数获取指定的Bean对象
* 它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
*/
public interface BeanFactory {
Object getBean(String name) throws BeansException;
}
抽象类定义模板方法实现具体的getBean方法
cn.wen.springframework.beans.factory.support.AbstractBeanFactory
/**
* @ClassName: AbstractBeanFactory
* @Author: 小飞
* @Date: 2023/3/26 22:46
* @Description:
*/
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {
@Override
public Object getBean(String name) throws BeansException {
// 获取父类DefaultSingletonBeanRegistry中单例池中的单例对象
Object bean = getSingleton(name);
if (bean != null) {
return bean;
}
// 如果为空说明需要创建一个 Bean 对象那么就需要拿到对应的BeanDefinition对象存储了相关元数据
BeanDefinition beanDefinition = getBeanDefinition(name);
// 通过 beanName、BeanDefinition 来创建一个Bean对象但是这里只定义抽象方法由实现类来实现具体创建流程。
return createBean(name, beanDefinition);
}
protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
protected abstract Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException;
}
- 继承 DefaultSingletonBeanRegistry 默认的单例抽象类,同时也具备了使用单例注册类的方法。
- 重点:实现了接口 BeanFactory 的实现,方法 getBean 的实现过程中可以看到,主要是对单例 Bean 对象的获取以及在获取不到时需要拿到 Bean 的定义做相应 Bean 实例化操作。那么 getBean 并没有自身的去实现这些方法,而是只定义了调用过程以及提供了抽象方法,由实现此抽象类的其他类做相应实现。
- 那 AbstractBeanFactory 的实现类有哪些?主要包括 AbstractAutowireCapableBeanFactory、DefaultListableBeanFactory 来分别实现对应的 createBean、getBeanDefinition 方法。
1.2.1.5、实例化 Bean 类
cn.wen.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
/**
* @ClassName: AbstractAutowireCapableBeanFactory
* @Author: 小飞
* @Date: 2023/3/26 22:36
* @Description: 继承抽象类AbstractBeanFactory实现相应的抽象方法,实现其中的createBean方法
* 但是AbstractAutowireCapableBeanFactory 本身也是一个抽象类,
* 所以它只会实现属于自己的抽象方法,其他抽象方法由继承 AbstractAutowireCapableBeanFactory 的类实现。
* 这里就体现了类实现过程中的各司其职。
*/
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException {
Object bean;
try {
// 这里只能实现无参构造、一旦含参构造就会出错,所以后序会使用动态代理来实现创建Bean流程
bean = beanDefinition.getBeanClass().newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new BeansException("Instantiation of bean failed", e);
}
// 添加到单例次中,因为目前只实现单例操作
addSingleton(beanName, bean);
return bean;
}
}
- AbstractAutowireCapableBeanFactory 抽象类中实现了 Bean 的实例化操作,但是从上面的 beanDefinition.getBeanClass().newInstance() 可以看出这里只是无参构造,如果含参构造会出现异常,那么需要使用动态代理来实现含参构造。
- 在实例化完 Bean 对象后调用 DefaultSingletonBeanRegistry #addSingleton()方法将单例对象存储到缓存中。
1.2.1.6、核心类实现(DefaultListableBeanFactory)
cn.wen.springframework.beans.factory.support.DefaultListableBeanFactory
/**
* @ClassName: DefaultListableBeanFactory
* @Author: 小飞
* @Date: 2023/3/26 22:49
* @Description: 默认实现了ListableBeanFactory和BeanDefinitionRegistry接口,
* 基于BeanDefinition对象,是一个成熟的bean Factory。
* 就是作为一个独立存在的容器来存储Bean对象的一个类,
* 在访问bean前,需要注册所有的definition(可能从bean definition配置文件中)。
* 使用预先建立的bean定义元数据对象,从本地的BeanDefinition表中查询BeanDefinition因而将不会花费太多成本。
*/
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegistry{
private final Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
beanDefinitionMap.put(beanName, beanDefinition);
}
@Override
public BeanDefinition getBeanDefinition(String beanName) throws BeansException {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition == null) throw new BeansException("No bean named '" + beanName + "' is defined");
return beanDefinition;
}
}
- DefaultListableBeanFactory 在 Spring 源码中也是一个非常核心的类,在我们目前的实现中也是逐步贴近于源码,与源码类名保持一致。主要是通过 HashMap 来作为一个容器存储 Bean 对象。
- DefaultListableBeanFactory 继承了 AbstractAutowireCapableBeanFactory 类,也就具备了接口 BeanFactory 和 AbstractBeanFactory 等一连串的功能实现。所以有时候你会看到一些类的强转,调用某些方法,也是因为你强转的类实现接口或继承了某些类。
- 实现了 接口 BeanDefinitionRegistry 中的registerBeanDefinition(String beanName, BeanDefinition beanDefinition) 方法,当然你还会看到一个 getBeanDefinition 的实现,最后面都存储到了 DefaultListableBeanFactory #beanDefinitionMap 中。所以DefaultListableBeanFactory是Spring的核心类,不仅作为 Spring 的容器 而且还提供一些获取容器中对象的方法Api。
1.2.1.7、测试类
定义一个 UserService 对象作为待注册到Bean容器的目标对象。
cn.wen.springframework.test.bean.UserService
/**
* @ClassName: UserService
* @Author: 小飞
* @Date: 2023/3/26 23:10
* @Description: 待注册类
*/
public class UserService {
public void queryUserInfo(){
System.out.println("查询用户信息");
}
}
测试类
@Test
public void testBeanFactory() {
// 1.初始化 BeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 2.注册 bean
BeanDefinition beanDefinition = new BeanDefinition(UserService.class);
beanFactory.registerBeanDefinition("userService", beanDefinition);
// 3.第一次获取 bean
UserService userService = (UserService) beanFactory.getBean("userService");
userService.queryUserInfo();
// 4.第二次获取 bean
UserService userServiceSingleton = (UserService) beanFactory.getSingleton("userService");
userServiceSingleton.queryUserInfo();
}
- 输出结果都是一样的,同时前者还未实例化时是需要进行实例化,后者第二次获取是会从内存中获取该Bean对象的,因为是单例模式。
1.2.2、基于CGLIB含参构造实例化策略
上一节我们也说明了 使用简单的实例化方法 beanDefinition.getBeanClass().newInstance() 只能实现无参构造,如果需要实现含参构造又该如何实现呢?
答案:使用动态代理来实现含参构造。一个是基于 Java 本身自带的方法 DeclaredConstructor,另外一个是使用 Cglib 来动态创建 Bean 对象。Cglib 是基于字节码框架 ASM 实现,所以你也可以直接通过 ASM 操作指令码来创建对象。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nQIgRT4N-1690811375709)(https://cdn.nlark.com/yuque/0/2023/png/25484710/1679847518667-6503ae21-9f4e-4345-a68d-f54302ebfa39.png#averageHue=%23f4e5c8&clientId=u2a79aa7b-398c-4&from=paste&height=355&id=ua0622172&originHeight=532&originWidth=1115&originalType=binary&ratio=1.5&rotation=0&showTitle=false&size=53596&status=done&style=none&taskId=u9cf5699b-761b-4d31-8ccd-b52bf63194f&title=&width=743.3333333333334)]
- 上面通过 两个动态代理的策略来实现含参构造,那么在 BeanFactory 中就需要添加一个获取Bean的方法了 Object getBean(String beanName, Object… args);将获取Bean时将构造函数的参数传入。
1.2.2.1、工程结构
下面使用 # 标识出了与上面模块修改的方法或者类
spring-framework
├─src
│ ├─main
│ │ ├─java
│ │ │ └─cn
│ │ │ └─wen
│ │ │ └─springframework
│ │ │ ├─beans
│ │ │ │ │ BeansException.java
│ │ │ │ │
│ │ │ │ └─factory
│ │ │ │ │ BeanFactory.java #
│ │ │ │ │
│ │ │ │ ├─config
│ │ │ │ │ BeanDefinition.java
│ │ │ │ │ SingletonBeanRegistry.java
│ │ │ │ │
│ │ │ │ └─support
│ │ │ │ AbstractAutowireCapableBeanFactory.java #
│ │ │ │ AbstractBeanFactory.java #
│ │ │ │ BeanDefinitionRegistry.java
│ │ │ │ CglibSubclassingInstantiationStrategy.java #
│ │ │ │ DefaultListableBeanFactory.java
│ │ │ │ DefaultSingletonBeanRegistry.java
│ │ │ │ InstantiationStrategy.java #
│ │ │ │ SimpleInstantiationStrategy.java #
│ │
│ └─test
│ └─java
│ └─cn
│ └─wen
│ └─springframework
│ └─test
│ │ ApiTest.java
│ │
│ └─bean
│ UserService.java
│
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hggydLhd-1690811375709)(https://cdn.nlark.com/yuque/0/2023/png/25484710/1679850089790-feb8e165-6bfd-467c-8666-41146bf5e5c5.png#averageHue=%23f6f5ec&clientId=u2a79aa7b-398c-4&from=paste&height=741&id=u5e49c9fc&originHeight=1111&originWidth=2173&originalType=binary&ratio=1.5&rotation=0&showTitle=false&size=195794&status=done&style=none&taskId=ufb72410d-880c-45c7-8616-fbc859c1aec&title=&width=1448.6666666666667)]
1.2.2.2、新增 getBean 接口
cn.wen.springframework.beans.factory.BeanFactory
/**
* @ClassName: BeanFactory
* @Author: 小飞
* @Date: 2023/3/25 21:24
* @Description: BeanFactory是实现IOC容器的核心接口,通过beanName或者beanName+参数获取指定的Bean对象
* 它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
*/
public interface BeanFactory {
// 空参构造
Object getBean(String name) throws BeansException;
// 含参构造
Object getBean(String name, Object... args) throws BeansException;
}
- BeanFactory 中重载了一个含有入参信息 args 的 getBean 方法,方便传递入参给构造函数实例。
1.2.2.3、实现类 AbstractBeanFactory
cn.wen.springframework.beans.factory.support.AbstractBeanFactory
/**
* @ClassName: AbstractBeanFactory
* @Author: 小飞
* @Date: 2023/3/26 22:46
* @Description:
*/
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null);
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
return doGetBean(name, args);
}
protected <T> T doGetBean(final String name, final Object[] args) {
// 获取父类DefaultSingletonBeanRegistry中单例池中的单例对象
Object bean = getSingleton(name);
if (bean != null) {
return (T) bean;
}
// 如果为空说明需要创建一个 Bean 对象那么就需要拿到对应的BeanDefinition对象存储了相关元数据
BeanDefinition beanDefinition = getBeanDefinition(name);
// 通过 beanName、BeanDefinition 来创建一个Bean对象但是这里只定义抽象方法由实现类来实现具体创建流程。
return (T) createBean(name, beanDefinition, args);
}
protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
protected abstract Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException;
}
- 重载getBean方法增加健壮性 提供含参方法获取Bean对象。
1.2.2.3、定义实例化策略接口
cn.wen.springframework.beans.factory.support.InstantiationStrategy
/**
* @ClassName: InstantiationStrategy
* @Author: 小飞
* @Date: 2023/3/27 0:33
* @Description: Bean 实例化策略,实例化策略的接口
*/
public interface InstantiationStrategy {
// 通过传入 BeanDefinition 数据类、参数、beanName 实现含参构造
Object instantiate(BeanDefinition beanDefinition, String beanName, Constructor ctor, Object[] args) throws BeansException;
}
- 实例化接口 instantiate 方法中添加必要的入参信息,包括:beanDefinition、 beanName、ctor、args
- Constructor 的作用就是匹配到符合对应参数的构造函数
- args 就是一个具体的入参信息,实例化需要使用到参数。
1.2.2.4、策略:JDK实例化
cn.wen.springframework.beans.factory.support.SimpleInstantiationStrategy
/**
* @ClassName: SimpleInstantiationStrategy
* @Author: 小飞
* @Date: 2023/3/27 0:35
* @Description: 通过JDK的DeclaredConstructor来实现含参构造
*/
public class SimpleInstantiationStrategy implements InstantiationStrategy {
@Override
public Object instantiate(BeanDefinition beanDefinition, String beanName, Constructor ctor, Object[] args) throws BeansException {
// 获取该 Bean 对象的反射类
Class clazz = beanDefinition.getBeanClass();
try {
// 传入的构造器不为空则进行含参构造实例化
if (null != ctor) {
return clazz.getDeclaredConstructor(ctor.getParameterTypes()).newInstance(args);
} else {
// 如果构造器为空说明是无参构造
return clazz.getDeclaredConstructor().newInstance();
}
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new BeansException("Failed to instantiate [" + clazz.getName() + "]", e);
}
}
}
- 可以通过BeanDefinition对象获取需要的元数据。包括反射类型。
- 接下来判断 ctor 是否为空,如果为空则是无构造函数实例化,否则就是需要有构造函数的实例化。
1.2.2.5、策略:Cglib 实例化
cn.wen.springframework.beans.factory.support.CglibSubclassingInstantiationStrategy
/**
* @ClassName: CglibSubclassingInstantiationStrategy
* @Author: 小飞
* @Date: 2023/3/27 0:37
* @Description: Cglib 动态代理策略来实现含参构造实例化
*/
public class CglibSubclassingInstantiationStrategy implements InstantiationStrategy{
@Override
public Object instantiate(BeanDefinition beanDefinition, String beanName, Constructor ctor, Object[] args) throws BeansException {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(beanDefinition.getBeanClass());
enhancer.setCallback(new NoOp() {
@Override
public int hashCode() {
return super.hashCode();
}
});
// 下面也是通过传入的构造函数是否为空来选择实例化方式为含参还是无参
if (null == ctor) return enhancer.create();
return enhancer.create(ctor.getParameterTypes(), args);
}
}
- 这里直接创建 含参或者无参构造器还是比较简单的。
1.2.2.6、创建策略调用
cn.wen.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
/**
* @ClassName: AbstractAutowireCapableBeanFactory
* @Author: 小飞
* @Date: 2023/3/26 22:36
* @Description: 继承抽象类AbstractBeanFactory实现相应的抽象方法,实现其中的createBean方法
* 但是AbstractAutowireCapableBeanFactory 本身也是一个抽象类,
* 所以它只会实现属于自己的抽象方法,其他抽象方法由继承 AbstractAutowireCapableBeanFactory 的类实现。
* 这里就体现了类实现过程中的各司其职。
*/
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {
// 默认的策略
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException {
Object bean = null;
try {
bean = createBeanInstance(beanDefinition, beanName, args);
} catch (Exception e) {
throw new BeansException("Instantiation of bean failed", e);
}
addSingleton(beanName, bean);
return bean;
}
protected Object createBeanInstance(BeanDefinition beanDefinition, String beanName, Object[] args) {
Constructor constructorToUse = null;
// 获取当前 Bean 对象的反射类
Class<?> beanClass = beanDefinition.getBeanClass();
// 通过反射类来获取构造函数
Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors();
// 匹配参数的数量
for (Constructor ctor : declaredConstructors) {
if (null != args && ctor.getParameterTypes().length == args.length) {
constructorToUse = ctor;
break;
}
}
// 调用代理接口中的实现类来实现实例化
return getInstantiationStrategy().instantiate(beanDefinition, beanName, constructorToUse, args);
}
public InstantiationStrategy getInstantiationStrategy() {
return instantiationStrategy;
}
public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
this.instantiationStrategy = instantiationStrategy;
}
}
- 首先在 AbstractAutowireCapableBeanFactory 抽象类中定义了一个创建对象的实例化策略属性类 InstantiationStrategy instantiationStrategy,将 Cglib 作为默认的实现类。
- beanClass.getDeclaredConstructors() 方式可以获取到你所有的构造函数,然后通过遍历来匹配构造函数和入参信息args,这里实现比较简单 只是进行了数量匹配。
1.2.2.7、测试类
public class UserService {
private String name;
public UserService(String name) {
this.name = name;
}
public void queryUserInfo() {
System.out.println("查询用户信息:" + name);
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("");
sb.append("").append(name);
return sb.toString();
}
}
@Test
public void testCglib() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class);
enhancer.setCallback(new NoOp() {
@Override
public int hashCode() {
return super.hashCode();
}
});
Object obj = enhancer.create(new Class[]{String.class}, new Object[]{"小飞"});
System.out.println(obj);
}
@Test
public void testNewInstance() throws IllegalAccessException, InstantiationException {
UserService userService = UserService.class.newInstance();
System.out.println(userService);
}
@Test
public void testConstructor() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class<UserService> userServiceClass = UserService.class;
Constructor<UserService> declaredConstructor = userServiceClass.getDeclaredConstructor(String.class);
UserService userService = declaredConstructor.newInstance("小飞");
System.out.println(userService);
}
@Test
public void testParameterTypes() throws Exception {
Class<UserService> beanClass = UserService.class;
Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors();
Constructor<?> constructor = null;
for (Constructor<?> ctor : declaredConstructors) {
if (ctor.getParameterTypes().length == 1) {
constructor = ctor;
break;
}
}
Constructor<UserService> declaredConstructor = beanClass.getDeclaredConstructor(constructor.getParameterTypes());
UserService userService = declaredConstructor.newInstance("小飞");
System.out.println(userService);
}
- 不同的测试构造器方法
1.2.3、注入属性和依赖对象
上一节实现了 Bean 对象的实例化,那么接下来就是需要对实例化的对象进行属性赋值,同时需要对依赖的对象进行渲染。对于属性的填充不只是 int、Long、String,还包括还没有实例化的对象属性,都需要在 Bean 创建时进行填充操作。(还有典型的三级缓存解决循环依赖后序再实现)
那么我们是在哪里填充信息呢?
还记不记得上面我们讲到的一个BeanFactory的实现类 AbstractAutowireCapableBeanFactory 实现了createBean的方法,也就是这里面进行属性填充,将BeanDefinition #propertyValues中解析的数据存储到Bean对象中。
- 属性填充要在类实例化创建之后,也就是需要在 AbstractAutowireCapableBeanFactory 的 createBean 方法中添加 applyPropertyValues 操作。
- 由于我们需要在创建Bean时候填充属性操作,那么就需要在 bean 定义 BeanDefinition 类中,添加 PropertyValues 信息。
- 另外是填充属性信息还包括了 Bean 的对象类型,也就是需要再定义一个 BeanReference。
1.2.3.1、工程结构
spring-framework
│
├─src
│ ├─main
│ │ ├─java
│ │ │ └─cn
│ │ │ └─wen
│ │ │ └─springframework
│ │ │ ├─beans
│ │ │ │ │ BeansException.java
│ │ │ │ │ PropertyValue.java #
│ │ │ │ │ PropertyValues.java #
│ │ │ │ │
│ │ │ │ └─factory
│ │ │ │ │ BeanFactory.java
│ │ │ │ │
│ │ │ │ ├─config
│ │ │ │ │ BeanDefinition.java #
│ │ │ │ │ BeanReference.java #
│ │ │ │ │ SingletonBeanRegistry.java
│ │ │ │ │
│ │ │ │ └─support
│ │ │ │ AbstractAutowireCapableBeanFactory.java #
│ │ │ │ AbstractBeanFactory.java
│ │ │ │ BeanDefinitionRegistry.java
│ │ │ │ CglibSubclassingInstantiationStrategy.java
│ │ │ │ DefaultListableBeanFactory.java
│ │ │ │ DefaultSingletonBeanRegistry.java
│ │ │ │ InstantiationStrategy.java
│ │ │ │ SimpleInstantiationStrategy.java
│ │
│ └─test
│ └─java
│ └─cn
│ └─wen
│ └─springframework
│ └─test
│ │ ApiTest.java
│ │
│ └─bean
│ UserService.java
│ UserDao.java
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jhb7pbMZ-1690811375709)(https://cdn.nlark.com/yuque/0/2023/png/25484710/1679905865838-2153c109-b5a0-493c-8224-96d81fe441c7.png#averageHue=%23f2f1e5&clientId=u71f91f54-f75c-4&from=paste&height=734&id=u9f4e1962&originHeight=1101&originWidth=1178&originalType=binary&ratio=1.5&rotation=0&showTitle=false&size=139846&status=done&style=none&taskId=ud140dba1-72f5-4904-89c1-eaa9dc81962&title=&width=785.3333333333334)]
- BeanReference:类引用类型
- PropertyValue:存储键值对的属性值
- PropertyValues:使用List集合包装了PropertyValue 对象。
- BeanDefinition(改动):添加了一个PropertyValues属性,作为解析配置文件后包装键值对的集合。
- **AbstractAutowireCapableBeanFactory(**改动类):在creatBean方法中补全了填充属性的操作代码。
1.2.3.2、类引用类型
cn.wen.springframework.beans.factory.config.BeanReference
/**
* @ClassName: BeanReference
* @Author: 小飞
* @Date: 2023/3/25 21:34
* @Description: Bean 的引用类型:定义引用类型名称
*/
public class BeanReference {
// 引用类型名称
private final String beanName;
public BeanReference(String beanName) {
this.beanName = beanName;
}
public String getBeanName() {
return beanName;
}
}
- 作为引用类型的定义类,定义了类型的名称。
1.2.3.3、定义属性
cn.wen.springframework.beans.PropertyValue
/**
* @ClassName: PropertyValue
* @Author: 小飞
* @Date: 2023/3/25 20:45
* @Description: Bean属性信息(属性键值对注入)
*/
public class PropertyValue {
// 属性名称
private final String name;
// 属性的值:包括基本类型(int、char等)和引用类型(BeanReference)
private final Object value;
public PropertyValue(String name, Object value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public Object getValue() {
return value;
}
}
cn.wen.springframework.beans.PropertyValues
/**
* @ClassName: PropertyValues
* @Author: 小飞
* @Date: 2023/3/25 20:45
* @Description: bean 属性键值对的封装
* 缓存了对 key-value 解析相关的信息,避免重复解析。存储多个PropertyValue对象,
* 创建出一个用于传递类中属性信息的类,因为属性可能会有很多,所以还需要定义一个集合包装下
*/
public class PropertyValues {
private final List<PropertyValue> propertyValueList = new ArrayList<>();
public void addPropertyValue(PropertyValue pv) {
this.propertyValueList.add(pv);
}
public PropertyValue[] getPropertyValues() {
return this.propertyValueList.toArray(new PropertyValue[0]);
}
public PropertyValue getPropertyValue(String propertyName) {
for (PropertyValue pv : this.propertyValueList) {
if (pv.getName().equals(propertyName)) {
return pv;
}
}
return null;
}
}
- 这两个类的作用就是创建出一个用于传递类中属性信息的类,因为属性可能会有很多,所以还需要定义一个集合包装下
1.2.3.4、BeanDefinition 补全
cn.wen.springframework.beans.factory.config.BeanDefinition
/**
* @ClassName: BeanDefinition
* @Author: 小飞
* @Date: 2023/3/25 21:06
* @Description: 用于保存Bean的相关信息,包括属性、构造方法参数、
* 依赖的Bean名称及是否单例、延迟加载等,它是实例化 Bean 的原材料,存储Bean初始化时的元数据
* Spring就是根据BeanDefinition中的信息实例化 Bean。
*/
public class BeanDefinition {
// scope类型:单例类型
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
// scope类型:原型类型
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
// 当前bean对象的class类型
private Class beanClass;
// 当前bean对象的属性列表
private PropertyValues propertyValues;
// 初始化方法名称
private String initMethodName;
// 销毁方法名称
private String destroyMethodName;
// scope类型默认类型:单例类型
private String scope = SCOPE_SINGLETON;
private boolean singleton = true;
private boolean prototype = false;
public BeanDefinition(Class beanClass) {
this(beanClass, null);
}
public BeanDefinition(Class beanClass, PropertyValues propertyValues) {
this.beanClass = beanClass;
this.propertyValues = propertyValues != null ? propertyValues : new PropertyValues();
}
public void setScope(String scope) {
this.scope = scope;
this.singleton = SCOPE_SINGLETON.equals(scope);
this.prototype = SCOPE_PROTOTYPE.equals(scope);
}
public boolean isSingleton() {
return singleton;
}
public boolean isPrototype() {
return prototype;
}
public Class getBeanClass() {
return beanClass;
}
public void setBeanClass(Class beanClass) {
this.beanClass = beanClass;
}
public PropertyValues getPropertyValues() {
return propertyValues;
}
public void setPropertyValues(PropertyValues propertyValues) {
this.propertyValues = propertyValues;
}
public String getInitMethodName() {
return initMethodName;
}
public void setInitMethodName(String initMethodName) {
this.initMethodName = initMethodName;
}
public String getDestroyMethodName() {
return destroyMethodName;
}
public void setDestroyMethodName(String destroyMethodName) {
this.destroyMethodName = destroyMethodName;
}
}
1.2.3.5、Bean 属性填充
cn.wen.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
/**
* @ClassName: AbstractAutowireCapableBeanFactory
* @Author: 小飞
* @Date: 2023/3/26 22:36
* @Description: 继承抽象类AbstractBeanFactory实现相应的抽象方法,实现其中的createBean方法
* 但是AbstractAutowireCapableBeanFactory 本身也是一个抽象类,
* 所以它只会实现属于自己的抽象方法,其他抽象方法由继承 AbstractAutowireCapableBeanFactory 的类实现。
* 这里就体现了类实现过程中的各司其职。
*/
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException {
Object bean = null;
try {
// 实例化 bean
bean = createBeanInstance(beanDefinition, beanName, args);
// 为 bean 对象填充属性
applyPropertyValues(beanName, bean, beanDefinition);
} catch (Exception e) {
throw new BeansException("Instantiation of bean failed", e);
}
addSingleton(beanName, bean);
return bean;
}
// 实例化
protected Object createBeanInstance(BeanDefinition beanDefinition, String beanName, Object[] args) {
Constructor constructorToUse = null;
// 获取当前 Bean 对象的反射类
Class<?> beanClass = beanDefinition.getBeanClass();
// 通过反射类来获取构造函数
Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors();
// 匹配参数的数量
for (Constructor ctor : declaredConstructors) {
if (null != args && ctor.getParameterTypes().length == args.length) {
constructorToUse = ctor;
break;
}
}
// 调用代理接口中的实现类来实现实例化
return getInstantiationStrategy().instantiate(beanDefinition, beanName, constructorToUse, args);
}
/**
* Bean 属性填充
*/
protected void applyPropertyValues(String beanName, Object bean, BeanDefinition beanDefinition) {
try {
PropertyValues propertyValues = beanDefinition.getPropertyValues();
for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
String name = propertyValue.getName();
Object value = propertyValue.getValue();
if (value instanceof BeanReference) {
// A 依赖 B,获取 B 的实例化
BeanReference beanReference = (BeanReference) value;
value = getBean(beanReference.getBeanName());
}
// 属性填充
BeanUtil.setFieldValue(bean, name, value);
}
} catch (Exception e) {
throw new BeansException("Error setting property values:" + beanName);
}
}
public InstantiationStrategy getInstantiationStrategy() {
return instantiationStrategy;
}
public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
this.instantiationStrategy = instantiationStrategy;
}
}
- 主要包括是三个方法 createBean、createBeanInstance、applyPropertyValues,这里将createBean方法中实例化之后添加一行applyPropertyValues调用代码实现属性填充。
- 在 applyPropertyValues 中,通过获取 beanDefinition.getPropertyValues() 循环进行属性填充操作,如果遇到的是 BeanReference,那么就需要递归获取 Bean 实例,调用 getBean 方法。
- 当把依赖的 Bean 对象创建完成后,会递归回现在属性填充中。这里需要注意我们并没有去处理循环依赖的问题,这部分内容较大,后续补充。BeanUtil.setFieldValue(bean, name, value) 是 hutool-all 工具类中的方法,你也可以自己实现
1.2.3.6、测试
cn.wen.springframework.test.bean.UserDao
public class UserDao {
// 模拟数据库记录
private static Map<String, String> hashMap = new HashMap<>();
static {
hashMap.put("10001", "小飞");
hashMap.put("10002", "小飞飞");
hashMap.put("10003", "小文");
}
public String queryUserName(String uId) {
return hashMap.get(uId);
}
}
cn.wen.springframework.test.bean.UserService
/**
* @ClassName: UserService
* @Author: 小飞
* @Date: 2023/3/26 23:10
* @Description: 待注册类
*/
public class UserService {
private String id;
private UserDao userDao;
public void queryUserInfo() {
System.out.println("查询用户信息:" + userDao.queryUserName(id));
}
public String getId() {
return id;
}
public void setId(String uId) {
this.id = uId;
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
cn.wen.springframework.test.ApiTest
/**
* @ClassName: ApiTest
* @Author: 小飞
* @Date: 2023/3/26 23:10
* @Description:
*/
public class ApiTest {
@Test
public void testBeanFactoryValue() {
// 1.初始化 BeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 2. UserDao 注册
beanFactory.registerBeanDefinition("userDao", new BeanDefinition(UserDao.class));
// 3. UserService 设置属性[id、userDao]
PropertyValues propertyValues = new PropertyValues();
propertyValues.addPropertyValue(new PropertyValue("id", "10001"));
propertyValues.addPropertyValue(new PropertyValue("userDao",new BeanReference("userDao")));
// 4. UserService 注入bean
BeanDefinition beanDefinition = new BeanDefinition(UserService.class, propertyValues);
beanFactory.registerBeanDefinition("userService", beanDefinition);
// 5. UserService 获取bean
UserService userService = (UserService) beanFactory.getBean("userService");
userService.queryUserInfo();
}
}
1.2.4、解析文件注册对象
上面使用到了BeanDefinition类是作为存储元数据的容器,里面包含一些是否单例,PropertyValue类型、初始化方法、销毁方法等参数。那么我们是从哪里拿到的数据呢?
我们可以从测试一样手动注入对应的数据,但是我们是不太可能让用户通过手动方式创建的,而是最好能通过配置文件的方式简化创建过程。
那么我们需要怎么实现配置文件方式简化创建过程呢?
答案:我们可以和其他的设计框架一样,规范好配置格式,然后我们再使用策略模式选择对应的解析方式来实现自动解析参数并且注入到对象中。我们需要在现有的 Spring 框架雏形中添加一个资源解析器,也就是能读取classpath、本地文件和云文件的配置内容。这些配置内容就是像使用 Spring 时配置的 Spring.xml 一样,里面会包括 Bean 对象的描述和属性信息。 在读取配置文件信息后,接下来就是对配置文件中的 Bean 描述信息解析后进行注册操作,把 Bean 对象注册到 Spring 容器中。
- 资源加载器属于相对独立的部分,是相当于一个工具类来实现 IO 类型的规定好格式的标签等类型读取,包括处理Class、本地、云环境中的文件信息。
- 资源加载之后,接下来就是解析和注册 Bean 到 Spring 中的操作,这部分实现需要和 DefaultListableBeanFactory 核心类结合起来,最后解析的数据都是注册到这个类中的Map容器中。
- 那么在实现的时候就设计好接口的实现层级关系,包括我们需要定义出 Bean 定义的读取接口 BeanDefinitionReader 以及做好对应的实现类,在实现类中完成对 Bean 对象的解析和注册。
1.2.4.1、工程结构
spring-framework
├─src
│ ├─main
│ │ ├─java
│ │ │ └─cn
│ │ │ └─wen
│ │ │ └─springframework
│ │ │ ├─beans
│ │ │ │ │ BeansException.java
│ │ │ │ │ PropertyValue.java
│ │ │ │ │ PropertyValues.java
│ │ │ │ │
│ │ │ │ └─factory
│ │ │ │ │ BeanFactory.java #
│ │ │ │ │ ConfigurableListableBeanFactory.java #
│ │ │ │ │ HierarchicalBeanFactory.java #
│ │ │ │ │ ListableBeanFactory.java #
│ │ │ │ │
│ │ │ │ ├─config
│ │ │ │ │ AutowireCapableBeanFactory.java #
│ │ │ │ │ BeanDefinition.java
│ │ │ │ │ BeanReference.java
│ │ │ │ │ ConfigurableBeanFactory.java #
│ │ │ │ │ SingletonBeanRegistry.java
│ │ │ │ │
│ │ │ │ ├─support
│ │ │ │ │ AbstractAutowireCapableBeanFactory.java #
│ │ │ │ │ AbstractBeanDefinitionReader.java #
│ │ │ │ │ AbstractBeanFactory.java #
│ │ │ │ │ BeanDefinitionReader.java #
│ │ │ │ │ BeanDefinitionRegistry.java
│ │ │ │ │ CglibSubclassingInstantiationStrategy.java
│ │ │ │ │ DefaultListableBeanFactory.java #
│ │ │ │ │ DefaultSingletonBeanRegistry.java
│ │ │ │ │ InstantiationStrategy.java
│ │ │ │ │ SimpleInstantiationStrategy.java
│ │ │ │ │
│ │ │ │ └─xml
│ │ │ │ XmlBeanDefinitionReader.java #
│ │ │ │
│ │ │ ├─core
│ │ │ │ └─io
│ │ │ │ ClassPathResource.java #
│ │ │ │ DefaultResourceLoader.java #
│ │ │ │ FileSystemResource.java #
│ │ │ │ Resource.java #
│ │ │ │ ResourceLoader.java #
│ │ │ │ UrlResource.java #
│ │ │ │
│ │ │ └─util
│ │ │ ClassUtils.java #
│ │
│ └─test
│ ├─java
│ │ └─cn
│ │ └─wen
│ │ └─springframework
│ │ └─test
│ │ │ ApiTest.java #
│ │ │
│ │ └─bean
│ │ UserDao.java
│ │ UserService.java #
│ │
│ └─resources
│ important.properties #
│ spring.xml #
│
- 实现 将Bean的定义、注册和初始化交给 Spring.xml 配置化处理,需要实现两个模块:资源加载、xml资源解析类,接口 Resource、ResourceLoader 的实现,而另外 BeanDefinitionReader 接口则是对资源的具体使用,将配置信息注册到 Spring 容器中去。
- 接口:BeanDefinitionReader、抽象类:AbstractBeanDefinitionReader、实现类:XmlBeanDefinitionReader,这三部分内容主要是合理清晰的处理了资源读取后的注册 Bean 容器操作。
- Resource:资源加载接口,下面有几个不同类型的资源加载类型实现类
- BeanDefinitionReader:重载不同参数类型的资源加载接口方法,通过实现类AbstractBeanDefinitionReader 来存储其中的资源加载器和实现BeanDefinition的注册类。
- AbstractBeanDefinitionReader:提供常见的属性:工作的 BeanFactory、资源加载器、用于加载 Bean类的类加载器等等。
- XmlBeanDefinitionReader:Xml 类型的资源加载解析器。
- BeanFactory:已经存在 Bean 工厂接口获取 Bean 对象,这次新增加了按照类型获取 Bean 的方法: T getBean(String name, Class requiredType)
- ListableBeanFactory:是一个扩展 Bean 工厂接口的接口,新增加了 getBeansOfType、getBeanDefinitionNames() 方法,在 Spring 源码中还有其他扩展方法。
- HierarchicalBeanFactory:在 Spring 源码中它提供了可以获取父类 BeanFactory 方法,属于是一种扩展工厂的层次子接口。作为一个分类子类分层的接口。
- AutowireCapableBeanFactory:是一个自动化处理 Bean 工厂配置的接口,目前案例工程中还没有做相应的实现,后续逐步完善。
- ConfigurableBeanFactory:可获取 BeanPostProcessor、BeanClassLoader等的一个配置化接口。
- ConfigurableListableBeanFactory:提供分析和修改Bean以及预先实例化的操作接口,不过目前只有一个 getBeanDefinition 方法。
1.2.4.2、资源加载工具
cn.wen.springframework.core.io.Resource
public interface Resource {
InputStream getInputStream() throws IOException;
}
- 在 Spring 框架下创建 core.io 核心包,在这个包中主要用于处理资源加载流。
- 定义 Resource 接口,提供获取 InputStream 流的方法,接下来再分别实现三种不同的流文件操作:classPath、FileSystem、URL
ClassPath:cn.wen.springframework.core.io.ClassPathResource
public class ClassPathResource implements Resource {
private final String path;
private ClassLoader classLoader;
public ClassPathResource(String path) {
this(path, (ClassLoader) null);
}
public ClassPathResource(String path, ClassLoader classLoader) {
Assert.notNull(path, "Path must not be null");
this.path = path;
this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
}
@Override
public InputStream getInputStream() throws IOException {
InputStream is = classLoader.getResourceAsStream(path);
if (is == null) {
throw new FileNotFoundException(
this.path + " cannot be opened because it does not exist");
}
return is;
}
}
- 这一部分的实现是用于通过 ClassLoader 读取ClassPath 下的文件信息,具体的读取过程主要是:classLoader.getResourceAsStream(path)
**FileSystem:**cn.wen.springframework.core.io.FileSystemResource
public class FileSystemResource implements Resource {
private final File file;
private final String path;
public FileSystemResource(File file) {
this.file = file;
this.path = file.getPath();
}
public FileSystemResource(String path) {
this.file = new File(path);
this.path = path;
}
@Override
public InputStream getInputStream() throws IOException {
return new FileInputStream(this.file);
}
public final String getPath() {
return this.path;
}
}
- 通过指定文件路径的方式读取文件信息,这部分大家肯定还是非常熟悉的,经常会读取一些txt、excel文件输出到控制台。
Url:cn.wen.springframework.core.io.UrlResource
public class UrlResource implements Resource {
private final URL url;
public UrlResource(URL url) {
Assert.notNull(url,"URL must not be null");
this.url = url;
}
@Override
public InputStream getInputStream() throws IOException {
URLConnection con = this.url.openConnection();
try {
return con.getInputStream();
}
catch (IOException ex){
if (con instanceof HttpURLConnection){
((HttpURLConnection) con).disconnect();
}
throw ex;
}
}
}
- 通过 HTTP 的方式读取云服务的文件,我们也可以把配置文件放到 GitHub 或者 Gitee 上。
1.2.4.3、包装资源加载器
按照资源加载的不同方式,资源加载器可以把这些方式集中到统一的类服务下进行处理,外部用户只需要传递资源地址即可,简化使用。
定义接口:cn.wen.springframework.core.io.ResourceLoader
public interface ResourceLoader {
String CLASSPATH_URL_PREFIX = "classpath:";
Resource getResource(String location);
}
- 定义获取资源接口,里面传递 location 地址即可。
实现接口:cn.wen.springframework.core.io.DefaultResourceLoader
public class DefaultResourceLoader implements ResourceLoader {
@Override
public Resource getResource(String location) {
Assert.notNull(location, "Location must not be null");
if (location.startsWith(CLASSPATH_URL_PREFIX)) {
return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()));
}
else {
try {
URL url = new URL(location);
return new UrlResource(url);
} catch (MalformedURLException e) {
return new FileSystemResource(location);
}
}
}
}
1.2.4.4、Bean 解析器接口
cn.wen.springframework.beans.factory.support.BeanDefinitionReader
/**
* @ClassName: BeanDefinitionReader
* @Author: 小飞
* @Date: 2023/3/27 17:32
* @Description: BeanDefinition 的解析器接口 定义接口方法
*/
public interface BeanDefinitionReader {
BeanDefinitionRegistry getRegistry();
ResourceLoader getResourceLoader();
void loadBeanDefinitions(Resource resource) throws BeansException;
void loadBeanDefinitions(Resource... resource) throws BeansException;
void loadBeanDefinitions(String location) throws BeansException;
}
- 这是一个简单的定义BeanDefinition解析器的方法接口,重载三个加载Bean定义的方法。
- 这里需要注意 getRegistry()、getResourceLoader(),都是用于提供给后面三个方法的工具,加载和注册,这两个方法的实现会包装到抽象类中,以免污染具体的接口实现方法。
1.2.4.5、Bean 解析器抽象类实现
cn.wen.springframework.beans.factory.support.AbstractBeanDefinitionReader
/**
* @ClassName: AbstractBeanDefinitionReader
* @Author: 小飞
* @Date: 2023/3/27 17:45
* @Description: 存储资源加载类型、和存储BeanDefinition的注册器
*/
public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader {
private final BeanDefinitionRegistry registry;
private ResourceLoader resourceLoader;
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, new DefaultResourceLoader());
}
public AbstractBeanDefinitionReader(BeanDefinitionRegistry registry, ResourceLoader resourceLoader) {
this.registry = registry;
this.resourceLoader = resourceLoader;
}
@Override
public BeanDefinitionRegistry getRegistry() {
return registry;
}
@Override
public ResourceLoader getResourceLoader() {
return resourceLoader;
}
}
- 抽象类把 BeanDefinitionReader 接口的前两个方法全部实现完了,并提供了构造函数,让外部的调用使用方,把Bean定义注入类,传递进来。
- 这样在接口 BeanDefinitionReader 的具体实现类中,就可以把解析后的 XML 文件中的 Bean 信息,注册到 Spring 容器去了。主要是提供了注册 Bean的操作方法。
1.2.4.6、解析XML注册Bean
cn.wen.springframework.beans.factory.xml.XmlBeanDefinitionReader
/**
* @ClassName: XmlBeanDefinitionReader
* @Author: 小飞
* @Date: 2023/3/27 17:44
* @Description: xml 文件解析器
*/
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
super(registry);
}
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry, ResourceLoader resourceLoader) {
super(registry, resourceLoader);
}
@Override
public void loadBeanDefinitions(Resource resource) throws BeansException {
try {
try (InputStream inputStream = resource.getInputStream()) {
doLoadBeanDefinitions(inputStream);
}
} catch (IOException | ClassNotFoundException e) {
throw new BeansException("IOException parsing XML document from " + resource, e);
}
}
@Override
public void loadBeanDefinitions(Resource... resources) throws BeansException {
for (Resource resource : resources) {
loadBeanDefinitions(resource);
}
}
@Override
public void loadBeanDefinitions(String location) throws BeansException {
ResourceLoader resourceLoader = getResourceLoader();
Resource resource = resourceLoader.getResource(location);
loadBeanDefinitions(resource);
}
protected void doLoadBeanDefinitions(InputStream inputStream) throws ClassNotFoundException {
Document doc = XmlUtil.readXML(inputStream);
Element root = doc.getDocumentElement();
NodeList childNodes = root.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
// 判断元素
if (!(childNodes.item(i) instanceof Element)) continue;
// 判断对象
if (!"bean".equals(childNodes.item(i).getNodeName())) continue;
// 解析标签
Element bean = (Element) childNodes.item(i);
String id = bean.getAttribute("id");
String name = bean.getAttribute("name");
String className = bean.getAttribute("class");
// 获取 Class,方便获取类中的名称
Class<?> clazz = Class.forName(className);
// 优先级 id > name
String beanName = StrUtil.isNotEmpty(id) ? id : name;
if (StrUtil.isEmpty(beanName)) {
beanName = StrUtil.lowerFirst(clazz.getSimpleName());
}
// 定义Bean
BeanDefinition beanDefinition = new BeanDefinition(clazz);
// 读取属性并填充
for (int j = 0; j < bean.getChildNodes().getLength(); j++) {
if (!(bean.getChildNodes().item(j) instanceof Element)) continue;
if (!"property".equals(bean.getChildNodes().item(j).getNodeName())) continue;
// 解析标签:property
Element property = (Element) bean.getChildNodes().item(j);
String attrName = property.getAttribute("name");
String attrValue = property.getAttribute("value");
String attrRef = property.getAttribute("ref");
// 获取属性值:引入对象、值对象
Object value = StrUtil.isNotEmpty(attrRef) ? new BeanReference(attrRef) : attrValue;
// 创建属性信息
PropertyValue propertyValue = new PropertyValue(attrName, value);
beanDefinition.getPropertyValues().addPropertyValue(propertyValue);
}
if (getRegistry().containsBeanDefinition(beanName)) {
throw new BeansException("Duplicate beanName[" + beanName + "] is not allowed");
}
// 注册 BeanDefinition
getRegistry().registerBeanDefinition(beanName, beanDefinition);
}
}
}
- 在 doLoadBeanDefinitions 方法中,主要是对xml的读取 XmlUtil.readXML(inputStream) 和元素 Element 解析。在解析的过程中通过循环操作,以此获取 Bean 配置以及配置中的 id、name、class、value、ref 信息。
- XmlBeanDefinitionReader 的核心就是解析xml配置文件 然后将解析的内容封装成PropertyValue对象,最后将PropertyValue 存储到一个PropertyValues集合中 存储到BeanDefinition对象中作为属性进行注入。
- 最后在获取父类提供的getRegistry() 接口获取Bean的注册类将当前封装的BeanDefinition对象注册到DefaultListableBeanFactory#beanDefinitionMap 中也就是容器中。
1.2.4.7、ListableBeanFactory 扩展接口
cn.wen.springframework.beans.factory.ListableBeanFactory
/**
* @ClassName: ListableBeanFactory
* @Author: 小飞
* @Date: 2023/3/27 17:25
* @Description: 枚举它们的所有bean信息,而不用一个个通过bean的名称或类型一个个查找。
*/
public interface ListableBeanFactory extends BeanFactory{
/**
* 按照类型返回 Bean 实例
* @param type
* @param <T>
* @return
* @throws BeansException
*/
<T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;
/**
* Return the names of all beans defined in this registry.
*
* 返回注册表中所有的Bean名称
*/
String[] getBeanDefinitionNames();
}
- 枚举它们的所有bean信息,而不用一个个通过bean的名称或类型一个个查找。或者通过一种类型返回所有的数据
1.2.4.8、AutowireCapableBeanFactory 自动化处理Bean配置
cn.wen.springframework.beans.factory.config.AutowireCapableBeanFactory
/**
* @ClassName: AutowireCapableBeanFactory
* @Author: 小飞
* @Date: 2023/3/27 17:28
* @Description: 为已经实例化的对象装配属性、实例化一个Bean,并自动装配,这些被装配的属性对象都是Spring管理的
*/
public interface AutowireCapableBeanFactory extends BeanFactory {
}
1.2.4.9、ConfigurableBeanFactory 配置化接口
cn.wen.springframework.beans.factory.config.ConfigurableBeanFactory
/**
* @ClassName: ConfigurableBeanFactory
* @Author: 小飞
* @Date: 2023/3/25 21:28
* @Description: 可配置的 BeanFactory ,定义了各种各样的配置能力(提供配置 BeanFactory 的各种方法),
* 如bean的作用域,bean 的 classLoader,添加 bean 的后置处理器,设置 bean 的创建状态,销毁 bean 等等。
* 但是我们简易的ConfigurableBeanFactory 不需要那么多方法,我们目前只实现Bean的类型、增加Bean后置处理器、销毁Bean方法。
*/
public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry{
// 单例类型
String SCOPE_SINGLETON = "singleton";
// 原型类型
String SCOPE_PROTOTYPE = "prototype";
}
- 可配置的BeanFactory工厂,定义各种配置能力,巨大的工厂接口。提供 配置 BeanFactory 的各种方法和配置参数等。
1.2.4.10、测试类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8cWih279-1690811375710)(https://cdn.nlark.com/yuque/0/2023/png/25484710/1679917482015-a89dc8d1-a8bb-4b50-a8fe-ed1950a2e875.png#averageHue=%23edf9e5&clientId=u71f91f54-f75c-4&from=paste&height=43&id=u1039bb64&originHeight=64&originWidth=269&originalType=binary&ratio=1.5&rotation=0&showTitle=false&size=4965&status=done&style=none&taskId=uf180f58c-2e66-4021-93e1-4f7f43f7b44&title=&width=179.33333333333334)]
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="userDao" class="cn.wen.springframework.test.bean.UserDao"/>
<bean id="userService" class="cn.wen.springframework.test.bean.UserService">
<property name="id" value="10001"/>
<property name="userDao" ref="userDao"/>
</bean>
</beans>
cn.wen.springframework.test.bean.UserDao
public class UserDao {
// 模拟数据库操作
private static Map<String, String> hashMap = new HashMap<>();
static {
hashMap.put("10001", "小飞");
hashMap.put("10002", "小飞飞");
hashMap.put("10003", "小文");
}
public String queryUserName(String uId) {
return hashMap.get(uId);
}
}
cn.wen.springframework.test.bean.UserService
/**
* @ClassName: UserService
* @Author: 小飞
* @Date: 2023/3/26 23:10
* @Description: 待注册类
*/
public class UserService {
private String id;
private UserDao userDao;
public String queryUserInfo() {
return userDao.queryUserName(id);
}
public String getId() {
return id;
}
public void setId(String uId) {
this.id = uId;
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
cn.wen.springframework.test.ApiTest
/**
* @ClassName: ApiTest
* @Author: 小飞
* @Date: 2023/3/26 23:10
* @Description:
*/
public class ApiTest {
private DefaultResourceLoader resourceLoader;
@Before
public void init() {
resourceLoader = new DefaultResourceLoader();
}
@Test
public void testClasspath() throws IOException {
Resource resource = resourceLoader.getResource("classpath:important.properties");
InputStream inputStream = resource.getInputStream();
String content = IoUtil.readUtf8(inputStream);
System.out.println(content);
}
@Test
public void testFile() throws IOException {
Resource resource = resourceLoader.getResource("src/test/resources/important.properties");
InputStream inputStream = resource.getInputStream();
String content = IoUtil.readUtf8(inputStream);
System.out.println(content);
}
@Test
public void testUrl() throws IOException {
Resource resource = resourceLoader.getResource("https://github.com/fuzhengwei/small-spring/important.properties");
InputStream inputStream = resource.getInputStream();
String content = IoUtil.readUtf8(inputStream);
System.out.println(content);
}
@Test
public void testXml() {
// 1.初始化 BeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 2. 读取配置文件&注册Bean
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("classpath:spring.xml");
// 3. 获取Bean对象调用方法
UserService userService = beanFactory.getBean("userService", UserService.class);
String result = userService.queryUserInfo();
System.out.println("测试结果:" + result);
}
}
1.2.5、实现应用上下文
在对容器中 Bean 的实例化过程添加扩展机制的同时,还需要把目前关于 Spring.xml 初始化和加载策略进行优化,因为我们不太可能让面向 Spring 本身开发的 DefaultListableBeanFactory 服务,直接给予用户使用。
- DefaultListableBeanFactory、XmlBeanDefinitionReader,是我们在目前 Spring 框架中对于服务功能测试的使用方式,它能很好的体现出 Spring 是如何对 xml 加载以及注册Bean对象的操作过程,但这种方式是面向 Spring 本身的,还不具备一定的扩展性。
- 就像我们现在需要提供出一个可以在 Bean 初始化过程中,完成对 Bean 对象的扩展时,就很难做到自动化处理。所以我们要把 Bean 对象扩展机制功能和对 Spring 框架上下文的包装融合起来,对外提供完整的服务。
- 满足于对 Bean 对象扩展的两个接口,其实也是 Spring 框架中非常具有重量级的两个接口:BeanFactoryPostProcessor 和 BeanPostProcessor,这两个接口都是 Bean的后置处理器,只不过BeanFactoryPostProcessor 是对于实例化前后的后置处理器而**BeanPostProcessor **初始化后置处理器。作用的时间不同,但是作用是差不多,都是扩展内部消息。
- BeanFactoryPostProcessor:是由 Spring 框架组建提供的容器扩展机制,允许在** Bean 对象注册后但未实例化之前**,对 Bean 的定义信息 BeanDefinition 执行修改操作。
- BeanPostProcessor:也是 Spring 提供的扩展机制,不过 BeanPostProcessor 是在 Bean 对象实例化之后修改 Bean 对象,也可以替换 Bean 对象。这部分与后面要实现的 AOP 有着密切的关系。
- 同时如果只是添加这两个接口,不做任何包装,那么对于使用者来说还是非常麻烦的。我们希望于开发 Spring 的上下文操作类(就相当一个控制类,控制Bean对象的创建,实例化,初始化一个周期的执行),把相应的 XML 加载 、注册、实例化以及新增的修改和扩展都融合进去,让 Spring 可以自动扫描到我们的新增服务,便于用户使用。
1.2.5.1、工程结构
│
├─src
│ ├─main
│ │ ├─java
│ │ │ └─cn
│ │ │ └─wen
│ │ │ └─springframework
│ │ │ ├─beans
│ │ │ │ │ BeansException.java
│ │ │ │ │ PropertyValue.java
│ │ │ │ │ PropertyValues.java
│ │ │ │ │
│ │ │ │ └─factory
│ │ │ │ │ BeanFactory.java
│ │ │ │ │ ConfigurableListableBeanFactory.java
│ │ │ │ │ HierarchicalBeanFactory.java
│ │ │ │ │ ListableBeanFactory.java
│ │ │ │ │
│ │ │ │ ├─config
│ │ │ │ │ AutowireCapableBeanFactory.java
│ │ │ │ │ BeanDefinition.java
│ │ │ │ │ BeanFactoryPostProcessor.java
│ │ │ │ │ BeanPostProcessor.java
│ │ │ │ │ BeanReference.java
│ │ │ │ │ ConfigurableBeanFactory.java
│ │ │ │ │ SingletonBeanRegistry.java
│ │ │ │ │
│ │ │ │ ├─support
│ │ │ │ │ AbstractAutowireCapableBeanFactory.java
│ │ │ │ │ AbstractBeanDefinitionReader.java
│ │ │ │ │ AbstractBeanFactory.java
│ │ │ │ │ BeanDefinitionReader.java
│ │ │ │ │ BeanDefinitionRegistry.java
│ │ │ │ │ CglibSubclassingInstantiationStrategy.java
│ │ │ │ │ DefaultListableBeanFactory.java
│ │ │ │ │ DefaultSingletonBeanRegistry.java
│ │ │ │ │ InstantiationStrategy.java
│ │ │ │ │ SimpleInstantiationStrategy.java
│ │ │ │ │
│ │ │ │ └─xml
│ │ │ │ XmlBeanDefinitionReader.java
│ │ │ │
│ │ │ ├─context
│ │ │ │ │ ApplicationContext.java
│ │ │ │ │ ConfigurableApplicationContext.java
│ │ │ │ │
│ │ │ │ └─support
│ │ │ │ AbstractApplicationContext.java
│ │ │ │ AbstractRefreshableApplicationContext.java
│ │ │ │ AbstractXmlApplicationContext.java
│ │ │ │ ClassPathXmlApplicationContext.java
│ │ │ │
│ │ │ ├─core
│ │ │ │ └─io
│ │ │ │ ClassPathResource.java
│ │ │ │ DefaultResourceLoader.java
│ │ │ │ FileSystemResource.java
│ │ │ │ Resource.java
│ │ │ │ ResourceLoader.java
│ │ │ │ UrlResource.java
│ │ │ │
│ │ │ └─util
│ │ │ ClassUtils.java
│ │
│ └─test
│ ├─java
│ │ └─cn
│ │ └─wen
│ │ └─springframework
│ │ └─test
│ │ │ ApiTest.java
│ │ │
│ │ ├─bean
│ │ │ UserDao.java
│ │ │ UserService.java
│ │ │
│ │ └─common
│ │ MyBeanFactoryPostProcessor.java
│ │ MyBeanPostProcessor.java
│ │
│ └─resources
│ important.properties
│ spring.xml
│ springPostProcessor.xml
│
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-39lwpCg1-1690811375711)(https://cdn.nlark.com/yuque/0/2023/png/25484710/1679922138848-11c69614-990b-4be1-a92f-8e1a44562ac5.png#averageHue=%23f2f1e2&clientId=u71f91f54-f75c-4&from=paste&height=746&id=u2ed44bf3&originHeight=1119&originWidth=1655&originalType=binary&ratio=1.5&rotation=0&showTitle=false&size=241557&status=done&style=none&taskId=u847cbe00-efe2-4bbc-aca9-8ccbe0fc7f9&title=&width=1103.3333333333333)]
- 图中体现出 关于 Spring 应用上下文(应用前后的关系)以及对 Bean 对象的实现。
- 继承了 ListableBeanFactory 接口的 ApplicationContext 接口开始,扩展出一系列应用上下文的抽象实现类,并最终完成 ClassPathXmlApplicationContext 类的实现。而这个类就是最后交给用户使用的类。
- ApplicationContext是BeanFactory派生来的,提供了更多面向实际应用的功能,就相当简化封装。
1.2.5.2、定义 BeanFactoryPostProcessor
cn.wen.springframework.beans.factory.config.BeanFactoryPostProcessor
/**
* @ClassName: BeanFactoryPostProcessor
* @Author: 小飞
* @Date: 2023/3/27 20:07
* @Description: 实例化之前对 bean 定义进行修改,实例化的后置处理器
*/
public interface BeanFactoryPostProcessor {
/**
* 在所有的 BeanDefinition 加载完成后,实例化 Bean 对象之前,提供修改 BeanDefinition 属性的机制
*
* @param beanFactory
* @throws BeansException
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
- 这个接口是满足于在所有的 BeanDefinition 加载完成后,实例化 Bean 对象之前,提供修改 BeanDefinition 属性的机制。
1.2.5.3、定义BeanPostProcessor
cn.wen.springframework.beans.factory.config.BeanPostProcessor
/**
* @ClassName: BeanPostProcessor
* @Author: 小飞
* @Date: 2023/3/25 21:32
* @Description: 用于修改新实例化 Bean 对象的扩展点(Bean初始化后置处理器 目的就是扩展功能)
*/
public interface BeanPostProcessor {
/**
* 在 Bean 对象执行初始化方法之前,执行此方法
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
/**
* 在 Bean 对象执行初始化方法之后,执行此方法
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
- 提供了修改新实例化 Bean 对象的扩展点,用于在 Bean 对象执行初始化方法之前,执行此方法、postProcessAfterInitialization用于在 Bean 对象执行初始化方法之后,执行此方法
1.2.5.4、补充 AutowireCapableBeanFactory
cn.wen.springframework.beans.factory.config.AutowireCapableBeanFactory
/**
* @ClassName: AutowireCapableBeanFactory
* @Author: 小飞
* @Date: 2023/3/27 17:28
* @Description: 为已经实例化的对象装配属性、实例化一个Bean,并自动装配,这些被装配的属性对象都是Spring管理的
*/
public interface AutowireCapableBeanFactory extends BeanFactory {
/**
* 执行 BeanPostProcessors 接口实现类的 postProcessBeforeInitialization 方法
*
* @param existingBean
* @param beanName
* @return
* @throws BeansException
*/
Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException;
/**
* 执行 BeanPostProcessors 接口实现类的 postProcessorsAfterInitialization 方法
*
* @param existingBean
* @param beanName
* @return
* @throws BeansException
*/
Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException;
}
- 自动装配的BeanFactory接口,就是执行 Bean对象中的 BeanPostProcessor 接口中对应的方法。
1.2.5.5、补充增加BeanPostProcessor方法
cn.wen.springframework.beans.factory.config.ConfigurableBeanFactory
/**
* @ClassName: ConfigurableBeanFactory
* @Author: 小飞
* @Date: 2023/3/25 21:28
* @Description: 可配置的 BeanFactory ,定义了各种各样的配置能力(提供配置 BeanFactory 的各种方法),
* 如bean的作用域,bean 的 classLoader,添加 bean 的后置处理器,设置 bean 的创建状态,销毁 bean 等等。
* 但是我们简易的ConfigurableBeanFactory 不需要那么多方法,我们目前只实现Bean的类型、增加Bean后置处理器、销毁Bean方法。
*/
public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry{
// 单例类型
String SCOPE_SINGLETON = "singleton";
// 原型类型
String SCOPE_PROTOTYPE = "prototype";
void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
}
- 增加方法 addBeanPostProcessor 增加到 AbstractBeanFactory#BeanPostProcessorList中
@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor){
this.beanPostProcessors.remove(beanPostProcessor);
this.beanPostProcessors.add(beanPostProcessor);
}
那么 BeanPostProcessor 是哪个地方使用呢?
1.2.5.6、补充 AbstractAutowireCapableBeanFactory
cn.wen.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
/**
* @ClassName: AbstractAutowireCapableBeanFactory
* @Author: 小飞
* @Date: 2023/3/26 22:36
* @Description: 继承抽象类AbstractBeanFactory实现相应的抽象方法,实现其中的createBean方法
* 但是AbstractAutowireCapableBeanFactory 本身也是一个抽象类,
* 所以它只会实现属于自己的抽象方法,其他抽象方法由继承 AbstractAutowireCapableBeanFactory 的类实现。
* 这里就体现了类实现过程中的各司其职。
*/
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException {
Object bean = null;
try {
// 实例化 bean
bean = createBeanInstance(beanDefinition, beanName, args);
// 为 bean 对象填充属性
applyPropertyValues(beanName, bean, beanDefinition);
// 执行 Bean 的初始化方法和 BeanPostProcessor 的前置和后置处理方法
bean = initializeBean(beanName, bean, beanDefinition);
} catch (Exception e) {
throw new BeansException("Instantiation of bean failed", e);
}
addSingleton(beanName, bean);
return bean;
}
// 实例化
protected Object createBeanInstance(BeanDefinition beanDefinition, String beanName, Object[] args) {
Constructor constructorToUse = null;
// 获取当前 Bean 对象的反射类
Class<?> beanClass = beanDefinition.getBeanClass();
// 通过反射类来获取构造函数
Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors();
// 匹配参数的数量
for (Constructor ctor : declaredConstructors) {
if (null != args && ctor.getParameterTypes().length == args.length) {
constructorToUse = ctor;
break;
}
}
// 调用代理接口中的实现类来实现实例化
return getInstantiationStrategy().instantiate(beanDefinition, beanName, constructorToUse, args);
}
/**
* Bean 属性填充
*/
protected void applyPropertyValues(String beanName, Object bean, BeanDefinition beanDefinition) {
try {
PropertyValues propertyValues = beanDefinition.getPropertyValues();
for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
String name = propertyValue.getName();
Object value = propertyValue.getValue();
if (value instanceof BeanReference) {
// A 依赖 B,获取 B 的实例化
BeanReference beanReference = (BeanReference) value;
value = getBean(beanReference.getBeanName());
}
// 属性填充
BeanUtil.setFieldValue(bean, name, value);
}
} catch (Exception e) {
throw new BeansException("Error setting property values:" + beanName);
}
}
public InstantiationStrategy getInstantiationStrategy() {
return instantiationStrategy;
}
public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
this.instantiationStrategy = instantiationStrategy;
}
private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) {
// 1. 执行 BeanPostProcessor Before 处理
Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
// 待完成内容:invokeInitMethods(beanName, wrappedBean, beanDefinition);
invokeInitMethods(beanName, wrappedBean, beanDefinition);
// 2. 执行 BeanPostProcessor After 处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
return wrappedBean;
}
private void invokeInitMethods(String beanName, Object wrappedBean, BeanDefinition beanDefinition) {
}
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (null == current) return result;
result = current;
}
return result;
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (null == current) return result;
result = current;
}
return result;
}
}
- 前面定义了 BeanPostProcessor 接口的后置处理方法 自然要用到,通过AbstractAutowireCapableBeanFactory # createBean 创建Bean对象后初始化前后通过调用AutowireCapableBeanFactory 接口中的两个方法来调用所有的 BeanPostProcessor 对象执行。
1.2.5.7、定义上下文接口
cn.wen.springframework.context.ApplicationContext
/**
* @ClassName: ApplicationContext
* @Author: 小飞
* @Date: 2023/3/27 20:17
* @Description: 应用上下文 是本次实现应用上下文功能新增的服务包
*/
public interface ApplicationContext extends ListableBeanFactory {
}
- context 是本次实现应用上下文功能新增的服务包
- ApplicationContext,继承于 ListableBeanFactory,也就继承了关于 BeanFactory 方法,比如一些 getBean 的方法。另外 ApplicationContext 本身是 Central 接口,但目前还不需要添加一些获取ID和父类上下文,所以暂时没有接口方法的定义。
cn.wen.springframework.context.ConfigurableApplicationContext
/**
* @ClassName: ConfigurableApplicationContext
* @Author: 小飞
* @Date: 2023/3/27 20:18
* @Description: 接下来也是需要在上下文的实现中完成刷新容器的操作过程
* 虚拟机关闭钩子注册调用销毁方法
*/
public interface ConfigurableApplicationContext extends ApplicationContext{
/**
* 刷新容器
*
* @throws BeansException
*/
void refresh() throws BeansException;
}
- configurableApplicationContext 继承自 ApplicationContext,并提供了 refresh 这个核心方法。
1.2.5.8、应用上下文抽象实现类
cn.wen.springframework.context.support.AbstractApplicationContext
/**
* @ClassName: AbstractApplicationContext
* @Author: 小飞
* @Date: 2023/3/27 20:19
* @Description:
*/
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
/**
* 执行刷新容器功能
* @throws BeansException
*/
@Override
public void refresh() throws BeansException {
// 1、实现创建bean工厂 BeanFactory 然后加载BeanDefinition
refreshBeanFactory();
// 2、获取BeanFactory
// 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
// 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
// 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 3、在Bean实例化之前;执行BeanFactoryPostProcessor 方法中的初始化前和初始化后
invokeBeanFactoryPostProcessors(beanFactory);
// 4、BeanPostProcess 需要提前与其他 Bean对象实例化之前进行注册操作
// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
registerBeanPostProcessors(beanFactory);
// 5、提前实例化单例Bean对象
beanFactory.preInstantiateSingletons();
}
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
Map<String, BeanPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class);
for (BeanPostProcessor beanPostProcessor : beanPostProcessorMap.values()) {
beanFactory.addBeanPostProcessor(beanPostProcessor);
}
}
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
Map<String, BeanFactoryPostProcessor> beanFactoryPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
for (BeanFactoryPostProcessor beanFactoryPostProcessor : beanFactoryPostProcessorMap.values()) {
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
}
}
protected abstract ConfigurableListableBeanFactory getBeanFactory();
protected abstract void refreshBeanFactory();
@Override
public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {
return getBeanFactory().getBeansOfType(type);
}
@Override
public String[] getBeanDefinitionNames() {
return getBeanFactory().getBeanDefinitionNames();
}
@Override
public Object getBean(String name) throws BeansException {
return getBeanFactory().getBean(name);
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
return getBeanFactory().getBean(name, args);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return getBeanFactory().getBean(name, requiredType);
}
}
- 方法内有一些抽象方法由该抽象类的子类实现具体的方法,不同的不同的继承类职责分工明确。
- AbstractApplicationContext 继承 DefaultResourceLoader 是为了处理 spring.xml 配置资源的加载。
- 之后是在 refresh() 定义实现过程,包括:
1. 创建 BeanFactory,并加载 BeanDefinition
2. 获取 BeanFactory
3. 在 Bean 实例化之前,执行 BeanFactoryPostProcessor ()
4. BeanPostProcessor 需要提前于其他 Bean 对象实例化之前执行注册操作
5. 提前实例化单例Bean对象 - 另外把定义出来的抽象方法,refreshBeanFactory()、getBeanFactory() 由后面的继承此抽象类的其他抽象类实现。
1.2.5.9、获取Bean工厂和加载资源
cn.wen.springframework.context.support.AbstractRefreshableApplicationContext
/**
* @ClassName: AbstractRefreshableApplicationContext
* @Author: 小飞
* @Date: 2023/3/27 20:21
* @Description: 要是获取了 DefaultListableBeanFactory 的实例化以及对资源配置的加载操作
*/
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext{
private DefaultListableBeanFactory beanFactory;
/**
* 判断是否存在旧的BeanFactory 如果存在则删除 创建一个新的BeanFactory
*/
@Override
protected void refreshBeanFactory() throws BeansException {
DefaultListableBeanFactory beanFactory = createBeanFactory();
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
}
private DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory();
}
protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory);
@Override
protected ConfigurableListableBeanFactory getBeanFactory() {
return beanFactory;
}
}
- 在 refreshBeanFactory() 中主要是获取了 DefaultListableBeanFactory 的实例化以及对资源配置的加载操作 loadBeanDefinitions(beanFactory),在加载完成后即可完成对 spring.xml 配置文件中 Bean 对象的定义和注册,同时也包括实现了接口 BeanFactoryPostProcessor、BeanPostProcessor 的配置 Bean 信息。
- 但此时资源加载还只是定义了一个抽象类方法 loadBeanDefinitions(DefaultListableBeanFactory beanFactory),继续由其他抽象类继承实现。
1.2.5.10、上下文配置信息加载
cn.wen.springframework.context.support.AbstractXmlApplicationContext
/**
* @ClassName: AbstractXmlApplicationContext
* @Author: 小飞
* @Date: 2023/3/27 20:22
* @Description: 抽象 Xml 上下文
*/
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableApplicationContext {
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory, this);
String[] configLocations = getConfigLocations();
if (null != configLocations){
beanDefinitionReader.loadBeanDefinitions(configLocations);
}
}
protected abstract String[] getConfigLocations();
}
- 在 AbstractXmlApplicationContext 抽象类的 loadBeanDefinitions 方法实现中,使用 XmlBeanDefinitionReader 类,处理了关于 XML 文件配置信息的操作。
- 同时这里又留下了一个抽象类方法,getConfigLocations(),此方法是为了从入口上下文类,拿到配置信息的地址描述。
1.2.5.11、应用上下文实现类
cn.wen.springframework.context.support.ClassPathXmlApplicationContext
/**
* @ClassName: ClassPathXmlApplicationContext
* @Author: 小飞
* @Date: 2023/3/27 20:25
* @Description: 实现 Xml 方式的上下文
*/
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext{
private String[] configLocations;
public ClassPathXmlApplicationContext() {
}
/**
* 从 XML 中加载 BeanDefinition,并刷新上下文
*
* @param configLocations
* @throws BeansException
*/
public ClassPathXmlApplicationContext(String configLocations) throws BeansException {
this(new String[]{configLocations});
}
/**
* 从 XML 中加载 BeanDefinition,并刷新上下文
* @param configLocations
* @throws BeansException
*/
public ClassPathXmlApplicationContext(String[] configLocations) throws BeansException {
this.configLocations = configLocations;
refresh();
}
@Override
protected String[] getConfigLocations() {
return configLocations;
}
}
- ClassPathXmlApplicationContext,是具体对外给用户提供的应用上下文方法。
- 在继承了 AbstractXmlApplicationContext 以及层层抽象类的功能分离实现后,在此类 ClassPathXmlApplicationContext 的实现中就简单多了,主要是对继承抽象类中方法的调用和提供了配置文件地址信息。
1.2.5.12、测试
cn.wen.springframework.test.bean.UserDao
public class UserDao {
// 模拟数据库操作
private static Map<String, String> hashMap = new HashMap<>();
static {
hashMap.put("10001", "小飞");
hashMap.put("10002", "小飞飞");
hashMap.put("10003", "小文");
}
public String queryUserName(String uId) {
return hashMap.get(uId);
}
}
cn.wen.springframework.test.bean.UserService
/**
* @ClassName: UserService
* @Author: 小飞
* @Date: 2023/3/26 23:10
* @Description: 待注册类
*/
public class UserService {
private String id;
private String company;
private String location;
private UserDao userDao;
public String queryUserInfo() {
return userDao.queryUserName(id) + "," + company + "," + location;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
cn.wen.springframework.test.common.MyBeanFactoryPostProcessor
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");
PropertyValues propertyValues = beanDefinition.getPropertyValues();
propertyValues.addPropertyValue(new PropertyValue("company", "改为:字节跳动"));
}
}
cn.wen.springframework.test.common.MyBeanPostProcessor
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
UserService userService = (UserService) bean;
userService.setLocation("改为:北京");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
cn.wen.springframework.test.ApiTest
/**
* @ClassName: ApiTest
* @Author: 小飞
* @Date: 2023/3/26 23:10
* @Description:
*/
public class ApiTest {
@Test
public void testBeanFactoryPostProcessorAndBeanPostProcessor(){
// 1.初始化 BeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 2. 读取配置文件&注册Bean
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("classpath:spring.xml");
// 3. BeanDefinition 加载完成 & Bean实例化之前,修改 BeanDefinition 的属性值
MyBeanFactoryPostProcessor beanFactoryPostProcessor = new MyBeanFactoryPostProcessor();
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
// 4. Bean实例化之后,修改 Bean 属性信息
MyBeanPostProcessor beanPostProcessor = new MyBeanPostProcessor();
beanFactory.addBeanPostProcessor(beanPostProcessor);
// 5. 获取Bean对象调用方法
UserService userService = beanFactory.getBean("userService", UserService.class);
String result = userService.queryUserInfo();
System.out.println("测试结果:" + result);
}
}
1.2.6、初始化和销毁方法
- 在 spring.xml 配置中添加 init-method、destroy-method 两个注解,在配置文件加载的过程中,把注解配置一并定义到 BeanDefinition 的属性当中。这样在 initializeBean 初始化操作的工程中,就可以通过反射的方式来调用配置在 Bean 定义属性当中的方法信息了。另外如果是接口实现的方式,那么直接可以通过 Bean 对象调用对应接口定义的方法即可,((InitializingBean) bean).afterPropertiesSet(),两种方式达到的效果是一样的。
- 除了在初始化做的操作外,destroy-method 和 DisposableBean 接口的定义,都会在 Bean 对象初始化完成阶段,执行注册销毁方法的信息到 DefaultSingletonBeanRegistry 类中的 disposableBeans 属性里,这是为了后续统一进行操作。DisposableBeanAdapter 的具体实现 -关于销毁方法需要在虚拟机执行关闭之前进行操作,所以这里需要用到一个注册钩子的操作,如:Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println(“close!”))); 这段代码你可以执行测试,另外你可以使用手动调用 ApplicationContext.close 方法关闭容器。
1.2.6.1、工程结构
spring-framework
│
├─src
│ ├─main
│ │ ├─java
│ │ │ └─cn
│ │ │ └─wen
│ │ │ └─springframework
│ │ │ ├─beans
│ │ │ │ │ BeansException.java
│ │ │ │ │ PropertyValue.java
│ │ │ │ │ PropertyValues.java
│ │ │ │ │
│ │ │ │ └─factory
│ │ │ │ │ BeanFactory.java
│ │ │ │ │ ConfigurableListableBeanFactory.java
│ │ │ │ │ DisposableBean.java #
│ │ │ │ │ HierarchicalBeanFactory.java
│ │ │ │ │ InitializingBean.java #
│ │ │ │ │ ListableBeanFactory.java
│ │ │ │ │
│ │ │ │ ├─config
│ │ │ │ │ AutowireCapableBeanFactory.java
│ │ │ │ │ BeanDefinition.java #
│ │ │ │ │ BeanFactoryPostProcessor.java
│ │ │ │ │ BeanPostProcessor.java
│ │ │ │ │ BeanReference.java
│ │ │ │ │ ConfigurableBeanFactory.java #
│ │ │ │ │ SingletonBeanRegistry.java
│ │ │ │ │
│ │ │ │ ├─support
│ │ │ │ │ AbstractAutowireCapableBeanFactory.java #
│ │ │ │ │ AbstractBeanDefinitionReader.java
│ │ │ │ │ AbstractBeanFactory.java
│ │ │ │ │ BeanDefinitionReader.java
│ │ │ │ │ BeanDefinitionRegistry.java
│ │ │ │ │ CglibSubclassingInstantiationStrategy.java
│ │ │ │ │ DefaultListableBeanFactory.java
│ │ │ │ │ DefaultSingletonBeanRegistry.java #
│ │ │ │ │ DisposableBeanAdapter.java #
│ │ │ │ │ InstantiationStrategy.java
│ │ │ │ │ SimpleInstantiationStrategy.java
│ │ │ │ │
│ │ │ │ └─xml
│ │ │ │ XmlBeanDefinitionReader.java #
│ │ │ │
│ │ │ ├─context
│ │ │ │ │ ApplicationContext.java
│ │ │ │ │ ConfigurableApplicationContext.java #
│ │ │ │ │
│ │ │ │ └─support
│ │ │ │ AbstractApplicationContext.java #
│ │ │ │ AbstractRefreshableApplicationContext.java
│ │ │ │ AbstractXmlApplicationContext.java
│ │ │ │ ClassPathXmlApplicationContext.java
│ │ │ │
│ │ │ ├─core
│ │ │ │ └─io
│ │ │ │ ClassPathResource.java
│ │ │ │ DefaultResourceLoader.java
│ │ │ │ FileSystemResource.java
│ │ │ │ Resource.java
│ │ │ │ ResourceLoader.java
│ │ │ │ UrlResource.java
│ │ │ │
│ │ │ └─util
│ │ │ ClassUtils.java
│ │ │
│ │ └─resources
│ │ important.properties
│ │ spring.xml
│ │ springPostProcessor.xml
│ │
│ └─test
│ ├─java
│ │ └─cn
│ │ └─wen
│ │ └─springframework
│ │ └─test
│ │ │ ApiTest.java
│ │ │
│ │ ├─bean
│ │ │ UserDao.java #
│ │ │ UserService.java
│ │
│ └─resources
│ important.properties
│ spring.xml
│ springPostProcessor.xml
│
- InitializingBean:该接口为 Bean 提供初始化方法的方式
- DisposableBean: 该接口为 Bean 提供销毁方法的方式
- XmlBeanDefinitionReader:增加解析init-method和destroy-method的代码块
- ConfigurableApplicationContext:增加注册清理功能的接口方法和close方法
- AbstractApplicationContext:增加实现清除操作和关闭存在
- DefaultSingletonBeanRegistry:实现ConfigurableBeanFactory 接口定义的destroySingletons方法
- BeanDefinition:添加解析后的初始化和销毁的定义
- ConfigurableBeanFactory:增加销毁单例对象的方法定义
- **AbstractAutowireCapableBeanFactory:**初始化后将销毁操作注册到Bean对象中。
- DisposableBeanAdapter:实现DisposableBean 接口定义的销毁方法。
1.2.6.2、定义初始化和销毁的接口
cn.wen.springframework.beans.factory.InitializingBean
/**
* @ClassName: InitializingBean
* @Author: 小飞
* @Date: 2023/3/27 22:26
* @Description: 实现此接口的 Bean 对象,会在 BeanFactory 设置属性后作出相应的处理,
* 如:执行自定义初始化,或者仅仅检查是否设置了所有强制属性。
*/
public interface InitializingBean {
/**
* Bean 处理了属性填充后调用
*
* @throws Exception
*/
void afterPropertiesSet() throws Exception;
}
cn.wen.springframework.beans.factory.DisposableBean
/**
* @ClassName: DisposableBean
* @Author: 小飞
* @Date: 2023/3/27 22:25
* @Description: 销毁 Bean 对象的接口
*/
public interface DisposableBean {
void destroy() throws Exception;
}
- InitializingBean、DisposableBean,两个接口方法还是比较常用的,在一些需要结合 Spring 实现的组件中,经常会使用这两个方法来做一些参数的初始化和销毁操作。比如接口暴漏、数据库数据读取、配置文件加载等等。
1.2.6.3、Bean 属性新增初始化和销毁
cn.wen.springframework.beans.factory.config.BeanDefinition
/**
* @ClassName: BeanDefinition
* @Author: 小飞
* @Date: 2023/3/25 21:06
* @Description: 用于保存Bean的相关信息,包括属性、构造方法参数、
* 依赖的Bean名称及是否单例、延迟加载等,它是实例化 Bean 的原材料,存储Bean初始化时的元数据
* Spring就是根据BeanDefinition中的信息实例化 Bean。
*/
public class BeanDefinition {
// scope类型:单例类型
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
// scope类型:原型类型
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
// 当前bean对象的class类型
private Class beanClass;
// 当前bean对象的属性列表
private PropertyValues propertyValues;
// 初始化方法名称
private String initMethodName;
// 销毁方法名称
private String destroyMethodName;
// scope类型默认类型:单例类型
private String scope = SCOPE_SINGLETON;
private boolean singleton = true;
private boolean prototype = false;
public BeanDefinition(Class beanClass) {
this(beanClass, null);
}
public BeanDefinition(Class beanClass, PropertyValues propertyValues) {
this.beanClass = beanClass;
this.propertyValues = propertyValues != null ? propertyValues : new PropertyValues();
}
public void setScope(String scope) {
this.scope = scope;
this.singleton = SCOPE_SINGLETON.equals(scope);
this.prototype = SCOPE_PROTOTYPE.equals(scope);
}
public boolean isSingleton() {
return singleton;
}
public boolean isPrototype() {
return prototype;
}
public Class getBeanClass() {
return beanClass;
}
public void setBeanClass(Class beanClass) {
this.beanClass = beanClass;
}
public PropertyValues getPropertyValues() {
return propertyValues;
}
public void setPropertyValues(PropertyValues propertyValues) {
this.propertyValues = propertyValues;
}
public String getInitMethodName() {
return initMethodName;
}
public void setInitMethodName(String initMethodName) {
this.initMethodName = initMethodName;
}
public String getDestroyMethodName() {
return destroyMethodName;
}
public void setDestroyMethodName(String destroyMethodName) {
this.destroyMethodName = destroyMethodName;
}
}
- BeanDefinition 类中新增了2个属性分别是 initMethodName、destroyMethodName,这两个属性在配置spring.xml 配置的Bean 对象中,init-method=“initDataMethod” destroy-method=“destroyDataMethod”
cn.wen.springframework.beans.factory.xml.XmlBeanDefinitionReader
/**
* @ClassName: XmlBeanDefinitionReader
* @Author: 小飞
* @Date: 2023/3/27 17:44
* @Description: xml 文件解析器
*/
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
super(registry);
}
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry, ResourceLoader resourceLoader) {
super(registry, resourceLoader);
}
@Override
public void loadBeanDefinitions(Resource resource) throws BeansException {
try {
try (InputStream inputStream = resource.getInputStream()) {
doLoadBeanDefinitions(inputStream);
}
} catch (IOException | ClassNotFoundException e) {
throw new BeansException("IOException parsing XML document from " + resource, e);
}
}
@Override
public void loadBeanDefinitions(Resource... resources) throws BeansException {
for (Resource resource : resources) {
loadBeanDefinitions(resource);
}
}
@Override
public void loadBeanDefinitions(String location) throws BeansException {
ResourceLoader resourceLoader = getResourceLoader();
Resource resource = resourceLoader.getResource(location);
loadBeanDefinitions(resource);
}
@Override
public void loadBeanDefinitions(String... locations) throws BeansException {
for (String location : locations) {
loadBeanDefinitions(location);
}
}
protected void doLoadBeanDefinitions(InputStream inputStream) throws ClassNotFoundException {
Document doc = XmlUtil.readXML(inputStream);
Element root = doc.getDocumentElement();
NodeList childNodes = root.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
// 判断元素
if (!(childNodes.item(i) instanceof Element)) continue;
// 判断对象
if (!"bean".equals(childNodes.item(i).getNodeName())) continue;
// 解析标签
Element bean = (Element) childNodes.item(i);
String id = bean.getAttribute("id");
String name = bean.getAttribute("name");
String className = bean.getAttribute("class");
String initMethod = bean.getAttribute("init-method");
String destroyMethodName = bean.getAttribute("destroy-method");
// 获取 Class,方便获取类中的名称
Class<?> clazz = Class.forName(className);
// 优先级 id > name
String beanName = StrUtil.isNotEmpty(id) ? id : name;
if (StrUtil.isEmpty(beanName)) {
beanName = StrUtil.lowerFirst(clazz.getSimpleName());
}
// 定义Bean
BeanDefinition beanDefinition = new BeanDefinition(clazz);
beanDefinition.setInitMethodName(initMethod);
beanDefinition.setDestroyMethodName(destroyMethodName);
// 读取属性并填充
for (int j = 0; j < bean.getChildNodes().getLength(); j++) {
if (!(bean.getChildNodes().item(j) instanceof Element)) continue;
if (!"property".equals(bean.getChildNodes().item(j).getNodeName())) continue;
// 解析标签:property
Element property = (Element) bean.getChildNodes().item(j);
String attrName = property.getAttribute("name");
String attrValue = property.getAttribute("value");
String attrRef = property.getAttribute("ref");
// 获取属性值:引入对象、值对象
Object value = StrUtil.isNotEmpty(attrRef) ? new BeanReference(attrRef) : attrValue;
// 创建属性信息
PropertyValue propertyValue = new PropertyValue(attrName, value);
beanDefinition.getPropertyValues().addPropertyValue(propertyValue);
}
if (getRegistry().containsBeanDefinition(beanName)) {
throw new BeansException("Duplicate beanName[" + beanName + "] is not allowed");
}
// 注册 BeanDefinition
getRegistry().registerBeanDefinition(beanName, beanDefinition);
}
}
}
- 增加对新属性的解析读取,添加到BeanDefinition对象中
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BHespaUS-1690811375713)(https://cdn.nlark.com/yuque/0/2023/png/25484710/1679993351807-4cf64c58-db13-426f-ad18-40177ed85729.png#averageHue=%23f8f7f6&clientId=u71e01f5c-571e-4&from=paste&height=356&id=uc997a051&originHeight=534&originWidth=1245&originalType=binary&ratio=1.25&rotation=0&showTitle=false&size=102438&status=done&style=none&taskId=ucfb0b310-ee03-4c5b-ba92-71e1dac91e8&title=&width=830)]
1.2.6.4、执行Bean对象的初始化方法
cn.wen.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
/**
* @ClassName: AbstractAutowireCapableBeanFactory
* @Author: 小飞
* @Date: 2023/3/26 22:36
* @Description: 继承抽象类AbstractBeanFactory实现相应的抽象方法,实现其中的createBean方法
* 但是AbstractAutowireCapableBeanFactory 本身也是一个抽象类,
* 所以它只会实现属于自己的抽象方法,其他抽象方法由继承 AbstractAutowireCapableBeanFactory 的类实现。
* 这里就体现了类实现过程中的各司其职。
*/
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException {
Object bean = null;
try {
// 实例化 bean
bean = createBeanInstance(beanDefinition, beanName, args);
// 为 bean 对象填充属性
applyPropertyValues(beanName, bean, beanDefinition);
// 执行 Bean 的初始化方法和 BeanPostProcessor 的前置和后置处理方法
bean = initializeBean(beanName, bean, beanDefinition);
} catch (Exception e) {
throw new BeansException("Instantiation of bean failed", e);
}
// 注册实现了 DisposableBean 接口的 Bean 对象
registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);
addSingleton(beanName, bean);
return bean;
}
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, BeanDefinition beanDefinition) {
if (bean instanceof DisposableBean || StrUtil.isNotEmpty(beanDefinition.getDestroyMethodName())) {
registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, beanDefinition));
}
}
// 实例化
protected Object createBeanInstance(BeanDefinition beanDefinition, String beanName, Object[] args) {
Constructor constructorToUse = null;
// 获取当前 Bean 对象的反射类
Class<?> beanClass = beanDefinition.getBeanClass();
// 通过反射类来获取构造函数
Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors();
// 匹配参数的数量
for (Constructor ctor : declaredConstructors) {
if (null != args && ctor.getParameterTypes().length == args.length) {
constructorToUse = ctor;
break;
}
}
// 调用代理接口中的实现类来实现实例化
return getInstantiationStrategy().instantiate(beanDefinition, beanName, constructorToUse, args);
}
/**
* Bean 属性填充
*/
protected void applyPropertyValues(String beanName, Object bean, BeanDefinition beanDefinition) {
try {
PropertyValues propertyValues = beanDefinition.getPropertyValues();
for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
String name = propertyValue.getName();
Object value = propertyValue.getValue();
if (value instanceof BeanReference) {
// A 依赖 B,获取 B 的实例化
BeanReference beanReference = (BeanReference) value;
value = getBean(beanReference.getBeanName());
}
// 属性填充
BeanUtil.setFieldValue(bean, name, value);
}
} catch (Exception e) {
throw new BeansException("Error setting property values:" + beanName);
}
}
public InstantiationStrategy getInstantiationStrategy() {
return instantiationStrategy;
}
public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
this.instantiationStrategy = instantiationStrategy;
}
private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) throws Exception {
// 1. 执行 BeanPostProcessor Before 处理
Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
// 待完成内容:invokeInitMethods(beanName, wrappedBean, beanDefinition);
invokeInitMethods(beanName, wrappedBean, beanDefinition);
// 2. 执行 BeanPostProcessor After 处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
return wrappedBean;
}
private void invokeInitMethods(String beanName, Object bean, BeanDefinition beanDefinition) throws Exception {
// 1. 实现接口 InitializingBean 判断是否实现了初始化接口
if (bean instanceof InitializingBean) {
((InitializingBean) bean).afterPropertiesSet();
}
// 2. 注解配置 init-method {判断是为了避免二次执行初始化}
String initMethodName = beanDefinition.getInitMethodName();
if (StrUtil.isNotEmpty(initMethodName) && !(bean instanceof InitializingBean)) {
Method initMethod = beanDefinition.getBeanClass().getMethod(initMethodName);
if (null == initMethod) {
throw new BeansException("Could not find an init method named '" + initMethodName + "' on bean with name '" + beanName + "'");
}
initMethod.invoke(bean);
}
}
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (null == current) return result;
result = current;
}
return result;
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (null == current) return result;
result = current;
}
return result;
}
}
- 抽象类 AbstractAutowireCapableBeanFactory 中createBean是创建Bean 对象的方法,方法之前已经扩展了 BeanFactoryPostProcessor、BeanPostProcessor 操作,然后增加 Bean对象的初始化操作
- 处理 afterPropertiesSet 方法。另外一个是判断配置信息 init-method 是否存在,执行反射调用 initMethod.invoke(bean)。这两种方式都可以在 Bean 对象初始化过程中进行处理加载 Bean 对象中的初始化操作,让使用者可以额外新增加自己想要的动作。
1.2.6.5、定义销毁方法适配器(接口和配置)
cn.wen.springframework.beans.factory.support.DisposableBeanAdapter
/**
* @ClassName: DisposableBeanAdapter
* @Author: 小飞
* @Date: 2023/3/27 22:30
* @Description:
*/
public class DisposableBeanAdapter implements DisposableBean {
private final Object bean;
private final String beanName;
private String destroyMethodName;
public DisposableBeanAdapter(Object bean, String beanName, BeanDefinition beanDefinition) {
this.bean = bean;
this.beanName = beanName;
this.destroyMethodName = beanDefinition.getDestroyMethodName();
}
// 需要先判断是否实现了销毁的表示接口 如果实现了就调用销毁的方法
@Override
public void destroy() throws Exception {
// 1. 实现接口 DisposableBean
if (bean instanceof DisposableBean) {
((DisposableBean) bean).destroy();
}
// 2. 注解配置 destroy-method {判断是为了避免二次执行销毁}
if (StrUtil.isNotEmpty(destroyMethodName) && !(bean instanceof DisposableBean && "destroy".equals(this.destroyMethodName))) {
Method destroyMethod = bean.getClass().getMethod(destroyMethodName);
if (null == destroyMethod) {
throw new BeansException("Couldn't find a destroy method named '" + destroyMethodName + "' on bean with name '" + beanName + "'");
}
destroyMethod.invoke(bean);
}
}
}
- 销毁方法有很多,目前可以实现接口 DisposableBean、配置信息 destroy-method 两种方式,两种销毁方式都是有 AbstractApplicationContext 注册虚钩子后的操作。
- 销毁执行的时候不想关注那么多,所以需要一个接口进行操作,不关系具体的销毁选择方案。
1.2.6.6、实现注册销毁策略和销毁单例
cn.wen.springframework.beans.factory.support.DefaultSingletonBeanRegistry
/**
* @ClassName: DefaultSingletonBeanRegistry
* @Author: 小飞
* @Date: 2023/3/26 22:37
* @Description: 默认的单例注册实现类,实现单例接口中规范的方法,获取单例的Bean对象等信息。
* 之后会被抽象类AbstractBeanFactory 工厂继承。
*/
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {
private final Map<String, Object> singletonObjects = new HashMap<>();
private final Map<String, DisposableBean> disposableBeans = new HashMap<>();
@Override
public Object getSingleton(String beanName) {
return singletonObjects.get(beanName);
}
@Override
public void registerSingleton(String beanName, Object singletonObject) {
}
protected void addSingleton(String beanName, Object singletonObject) {
singletonObjects.put(beanName, singletonObject);
}
public void registerDisposableBean(String beanName, DisposableBean bean) {
disposableBeans.put(beanName, bean);
}
public void destroySingletons() {
Set<String> keySet = this.disposableBeans.keySet();
Object[] disposableBeanNames = keySet.toArray();
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
Object beanName = disposableBeanNames[i];
DisposableBean disposableBean = disposableBeans.remove(beanName);
try {
disposableBean.destroy();
} catch (Exception e) {
throw new BeansException("Destroy method on bean with name '" + beanName + "' threw an exception", e);
}
}
}
}
- 实现 ConfigurableBeanFactory 接口定义的 destroySingletons 方法。
1.2.6.7、创建Bean时注册销毁对象
cn.wen.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException {
Object bean = null;
try {
bean = createBeanInstance(beanDefinition, beanName, args);
// 给 Bean 填充属性
applyPropertyValues(beanName, bean, beanDefinition);
// 执行 Bean 的初始化方法和 BeanPostProcessor 的前置和后置处理方法
bean = initializeBean(beanName, bean, beanDefinition);
} catch (Exception e) {
throw new BeansException("Instantiation of bean failed", e);
}
// 注册实现了 DisposableBean 接口的 Bean 对象
registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);
addSingleton(beanName, bean);
return bean;
}
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, BeanDefinition beanDefinition) {
if (bean instanceof DisposableBean || StrUtil.isNotEmpty(beanDefinition.getDestroyMethodName())) {
registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, beanDefinition));
}
}
}
- 上面提供了代码,这里就截取增加代码部分
- 创建 Bean 对象的实例的时候需要把销毁方法注册到 Bean 对象中,方便后序执行销毁操作。
- 那么这个销毁方法的具体方法信息,会被注册到 DefaultSingletonBeanRegistry 中新增加的 Map<String, DisposableBean> disposableBeans 属性中去,因为这个接口的方法最终可以被类 AbstractApplicationContext 的 close 方法通过 getBeanFactory().destroySingletons() 调用。
- 在注册销毁方法的时候,会根据是接口类型和配置类型统一交给 DisposableBeanAdapter 销毁适配器类来做统一处理。实现了某个接口的类可以被 instanceof 判断或者强转后调用接口方法
1.2.6.8、虚拟机关闭钩子注册和调用销毁方法
上面实例化时注册了销毁方法,那么下面就是这么调用
cn.wen.springframework.context.ConfigurableApplicationContext
/**
* @ClassName: ConfigurableApplicationContext
* @Author: 小飞
* @Date: 2023/3/27 20:18
* @Description: 接下来也是需要在上下文的实现中完成刷新容器的操作过程
* 虚拟机关闭钩子注册调用销毁方法
*/
public interface ConfigurableApplicationContext extends ApplicationContext{
/**
* 刷新容器
*
* @throws BeansException
*/
void refresh() throws BeansException;
void registerShutdownHook();
void close();
}
- 我们需要在ConfigurableApplicationContext 接口中定义 注册虚拟机钩子的方法 和 手动关闭的方法
cn.wen.springframework.context.support.AbstractApplicationContext
/**
* @ClassName: AbstractApplicationContext
* @Author: 小飞
* @Date: 2023/3/27 20:19
* @Description:
*/
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
/**
* 执行刷新容器功能
* @throws BeansException
*/
@Override
public void refresh() throws BeansException {
// 1、实现创建bean工厂 BeanFactory 然后加载BeanDefinition
refreshBeanFactory();
// 2、获取BeanFactory
// 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
// 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
// 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 3、在Bean实例化之前;执行BeanFactoryPostProcessor 方法中的初始化前和初始化后
invokeBeanFactoryPostProcessors(beanFactory);
// 4、BeanPostProcess 需要提前与其他 Bean对象实例化之前进行注册操作
// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
registerBeanPostProcessors(beanFactory);
// 5、提前实例化单例Bean对象
beanFactory.preInstantiateSingletons();
}
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
Map<String, BeanPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class);
for (BeanPostProcessor beanPostProcessor : beanPostProcessorMap.values()) {
beanFactory.addBeanPostProcessor(beanPostProcessor);
}
}
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
Map<String, BeanFactoryPostProcessor> beanFactoryPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
for (BeanFactoryPostProcessor beanFactoryPostProcessor : beanFactoryPostProcessorMap.values()) {
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
}
}
protected abstract ConfigurableListableBeanFactory getBeanFactory();
protected abstract void refreshBeanFactory();
@Override
public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {
return getBeanFactory().getBeansOfType(type);
}
@Override
public String[] getBeanDefinitionNames() {
return getBeanFactory().getBeanDefinitionNames();
}
@Override
public Object getBean(String name) throws BeansException {
return getBeanFactory().getBean(name);
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
return getBeanFactory().getBean(name, args);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return getBeanFactory().getBean(name, requiredType);
}
@Override
public void registerShutdownHook() {
Runtime.getRuntime().addShutdownHook(new Thread(this::close));
}
@Override
public void close() {
getBeanFactory().destroySingletons();
}
}
- 实现 注册钩子 和手动销毁的方法
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lTGfNZo5-1690811375713)(https://cdn.nlark.com/yuque/0/2023/png/25484710/1679994236444-6c75a14a-0d73-4f83-aac4-5d53911a7d44.png#averageHue=%23fcfbfa&clientId=u71e01f5c-571e-4&from=paste&height=185&id=ud9573ef5&originHeight=278&originWidth=1658&originalType=binary&ratio=1.25&rotation=0&showTitle=false&size=47219&status=done&style=none&taskId=u3aff3519-1440-491c-b361-4201620ebd3&title=&width=1105.3333333333333)]
1.2.6.9、测试
cn.wen.springframework.test.bean.UserDao
public class UserDao {
// 模拟数据库操作
private static Map<String, String> hashMap = new HashMap<>();
public void initDataMethod(){
System.out.println("执行:init-method");
hashMap.put("10001", "小飞");
hashMap.put("10002", "小飞飞");
hashMap.put("10003", "小飞飞");
}
public void destroyDataMethod(){
System.out.println("执行:destroy-method");
hashMap.clear();
}
public String queryUserName(String id) {
return hashMap.get(id);
}
}
cn.wen.springframework.test.bean.UserService
/**
* @ClassName: UserService
* @Author: 小飞
* @Date: 2023/3/26 23:10
* @Description: 待注册类
*/
public class UserService implements InitializingBean, DisposableBean {
private String id;
private String company;
private String location;
private UserDao userDao;
public String queryUserInfo() {
return userDao.queryUserName(id) + "," + company + "," + location;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void destroy() throws Exception {
System.out.println("执行:UserService.destroy");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("执行:UserService.destroy");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="userDao" class="cn.wen.springframework.test.bean.UserDao" init-method="initDataMethod" destroy-method="destroyDataMethod"/>
<bean id="userService" class="cn.wen.springframework.test.bean.UserService">
<property name="id" value="10001"/>
<property name="company" value="腾讯"/>
<property name="location" value="深圳"/>
<property name="userDao" ref="userDao"/>
</bean>
</beans>
@Test
public void test_xml() {
// 1.初始化 BeanFactory
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
applicationContext.registerShutdownHook();
// 2. 获取Bean对象调用方法
UserService userService = applicationContext.getBean("userService", UserService.class);
String result = userService.queryUserInfo();
System.out.println("测试结果:" + result);
}
@Test
public void test_hook() {
Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println("close!")));
}
1.2.7、Aware 感知容器对象
面向用户操作,我们不可能把 BeanFactoryPostProcessor 、BeanPostProcessor 这种类提供给用户操作吧,那么我们就需要扩展在这些框架被使用时怎么被调用,就需要提供一种能够感知容器操作的接口,能够获取接口入参中的各类功能。提供Aware接口可以让实现了该接口的 Bean 对象能够 感知容器的存在,可以让 Bean 对象使用容器提供的资源,可以调用服务的功能,就比如 ApplicationContextAware 接口实现了 Aware 接口,那么ApplicationContextAware 就拥有调用 ApplicationContext上下文的功能,我就可以通过实现ApplicationContextAware来获取ApplicationContext对象。
那么有人又会问:为什么 Bean 对象不直接拿到ApplicationContext对象呢?
这个我的理解应该是 Aware 是作为一个标识的作用,为什么不直接实现Aware接口,而是要在中间设计一个 不同类型的XxxAware接口比如ApplicationContextAware、BeanNameAware、BeanFactoryAware
其实他们代表不同功能的标识,实现了 ApplicationContextAware 就会拥有 ApplicationContext 对象的功能,实现了 BeanNameAware 接口就会拥有 获取当前Bean对象的名称功能,使用 Aware就是一个标识的作用,提供功能。
那么我们设计一个整体结构图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gHaJxicT-1690811375714)(https://cdn.nlark.com/yuque/0/2023/png/25484710/1679995826347-592ab885-062a-4d50-bb6a-924cfd7888c3.png#averageHue=%23f3ece9&clientId=u71e01f5c-571e-4&from=paste&height=598&id=u0c61755c&originHeight=897&originWidth=1699&originalType=binary&ratio=1.25&rotation=0&showTitle=false&size=141855&status=done&style=none&taskId=u63d249c1-efd6-4ca8-805a-f45e215eca4&title=&width=1132.6666666666667)]
- 定义接口 Aware,在 Spring 框架中它是一种感知标记性接口,具体的子类定义和实现能感知容器中的相关对象。可以通过具体的子类提供用户不同的功能。
- 继承 Aware 的接口目前包括:BeanFactoryAware、BeanClassLoaderAware、BeanNameAware和ApplicationContextAware
1.2.7.1、工程结构
spring-framework
│
├─src
│ ├─main
│ │ ├─java
│ │ │ └─cn
│ │ │ └─wen
│ │ │ └─springframework
│ │ │ ├─beans
│ │ │ │ │ BeansException.java
│ │ │ │ │ PropertyValue.java
│ │ │ │ │ PropertyValues.java
│ │ │ │ │
│ │ │ │ └─factory
│ │ │ │ │ Aware.java #
│ │ │ │ │ BeanClassLoaderAware.java #
│ │ │ │ │ BeanFactory.java
│ │ │ │ │ BeanFactoryAware.java #
│ │ │ │ │ BeanNameAware.java #
│ │ │ │ │ ConfigurableListableBeanFactory.java
│ │ │ │ │ DisposableBean.java
│ │ │ │ │ HierarchicalBeanFactory.java
│ │ │ │ │ InitializingBean.java
│ │ │ │ │ ListableBeanFactory.java
│ │ │ │ │
│ │ │ │ ├─config
│ │ │ │ │ AutowireCapableBeanFactory.java #
│ │ │ │ │ BeanDefinition.java
│ │ │ │ │ BeanFactoryPostProcessor.java
│ │ │ │ │ BeanPostProcessor.java
│ │ │ │ │ BeanReference.java
│ │ │ │ │ ConfigurableBeanFactory.java
│ │ │ │ │ SingletonBeanRegistry.java
│ │ │ │ │
│ │ │ │ ├─support
│ │ │ │ │ AbstractAutowireCapableBeanFactory.java #
│ │ │ │ │ AbstractBeanDefinitionReader.java
│ │ │ │ │ AbstractBeanFactory.java #
│ │ │ │ │ BeanDefinitionReader.java
│ │ │ │ │ BeanDefinitionRegistry.java
│ │ │ │ │ CglibSubclassingInstantiationStrategy.java
│ │ │ │ │ DefaultListableBeanFactory.java
│ │ │ │ │ DefaultSingletonBeanRegistry.java
│ │ │ │ │ DisposableBeanAdapter.java
│ │ │ │ │ InstantiationStrategy.java
│ │ │ │ │ SimpleInstantiationStrategy.java
│ │ │ │ │
│ │ │ │ └─xml
│ │ │ │ XmlBeanDefinitionReader.java
│ │ │ │
│ │ │ ├─context
│ │ │ │ │ ApplicationContext.java
│ │ │ │ │ ApplicationContextAware.java #
│ │ │ │ │ ConfigurableApplicationContext.java #
│ │ │ │ │
│ │ │ │ └─support
│ │ │ │ AbstractApplicationContext.java #
│ │ │ │ AbstractRefreshableApplicationContext.java #
│ │ │ │ AbstractXmlApplicationContext.java
│ │ │ │ ApplicationContextAwareProcessor.java #
│ │ │ │ ClassPathXmlApplicationContext.java
│ │ │ │
│ │ │ ├─core
│ │ │ │ └─io
│ │ │ │ ClassPathResource.java
│ │ │ │ DefaultResourceLoader.java
│ │ │ │ FileSystemResource.java
│ │ │ │ Resource.java
│ │ │ │ ResourceLoader.java
│ │ │ │ UrlResource.java
│ │ │ │
│ │ │ └─util
│ │ │ ClassUtils.java
│ │
│ └─test
│ ├─java
│ │ └─cn
│ │ └─wen
│ │ └─springframework
│ │ └─test
│ │ │ ApiTest.java
│ │ │
│ │ ├─bean
│ │ │ UserDao.java
│ │ │ UserService.java
│ │
│ └─resources
│ spring.xml
│
- Aware:标识类接口,作为一个标记接口,如果对象实现了此接口那么该对象就应用标识功能,通过instanceof 来判断该对象拥有的功能。
- BeanClassLoaderAware:作为BeanClassLoader的标识接口,提供当前类的类加载器
- BeanFactoryAware:作为 BeanFactory 的标识接口,对象可以获取到对应的BeanFactory对象。
- BeanNameAware:可以获取该Bean的名称
- ApplicationContextAware:应用上下文的标识接口,提供ApplicationContext 对象。
- ApplicationContextAwareProcessor:作为调用 ApplicationContext 的后置处理方法来为bean对象设置 ApplicationContext 对象,为 Bean 对象提供ApplicationContext。
- AbstractApplicationContext:整个容器的操作过程,增加了 addBeanPostProcessor 的操作,添加ApplicationContextAware 的后置处理方法,,让继承自 ApplicationContextAware 的 Bean 对象都能感知所属的 ApplicationContext。
- AbstractAutowireCapableBeanFactory:添加一些 Aware 感知的判断操作。
- AbstractBeanFactory:提供 当前线程的 ClassLoader 的抽象类。
1.2.7.2、定义标识接口
cn.wen.springframework.beans.factory.Aware
/**
* @ClassName: Aware
* @Author: 小飞
* @Date: 2023/3/28 17:35
* @Description: 感知顶层接口,标记类接口,实现该接口可以被Spring容器感知
*/
public interface Aware {
}
- 作为标识的接口它们的存在就像是一种标签一样,可以方便统一摘取出属于此类接口的实现类,通常会有 instanceof 一起判断使用。
1.2.7.3、容器感知类
cn.wen.springframework.beans.factory.BeanClassLoaderAware
/**
* @ClassName: BeanClassLoaderAware
* @Author: 小飞
* @Date: 2023/3/28 17:36
* @Description: 现此接口,既能感知到所属的 ClassLoader
*/
public interface BeanClassLoaderAware extends Aware{
void setBeanClassLoader(ClassLoader classLoader);
}
- 实现此接口,既能感知到所属的 ClassLoader
cn.wen.springframework.beans.factory.BeanFactoryAware
/**
* @ClassName: BeanFactoryAware
* @Author: 小飞
* @Date: 2023/3/28 17:37
* @Description: 实现此接口,既能感知到所属的 BeanFactory
*/
public interface BeanFactoryAware extends Aware{
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
- 实现此接口,既能感知到所属的 BeanFactory
cn.wen.springframework.beans.factory.BeanNameAware
/**
* @ClassName: BeanNameAware
* @Author: 小飞
* @Date: 2023/3/28 17:38
* @Description: 可以获取当前 Bean 的名称
*/
public interface BeanNameAware extends Aware {
void setBeanName(String name);
}
- 实现此接口,既能感知到该bean对象的名称
cn.wen.springframework.context.ApplicationContextAware
/**
* @ClassName: ApplicationContextAware
* @Author: 小飞
* @Date: 2023/3/28 17:38
* @Description: 实现此接口,既能感知到所属的 ApplicationContext
*/
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
- 实现此接口,既能感知到所属的 ApplicationContextAware
1.2.7.4、包装处理器
cn.wen.springframework.context.support.ApplicationContextAwareProcessor
/**
* @ClassName: ApplicationContextAwareProcessor
* @Author: 小飞
* @Date: 2023/3/28 17:45
* @Description: 装处理类
* 由于 ApplicationContext 的获取并不能直接在创建 Bean 时候就可以拿到,
* 所以需要在 refresh 操作时,把 ApplicationContext 写入到一个包装的
* BeanPostProcessor 中去,由 AbstractAutowireCapableBeanFactory.
* applyBeanPostProcessorsBeforeInitialization 方法调用
*/
public class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ApplicationContext applicationContext;
public ApplicationContextAwareProcessor(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 要判断并且将该bean的上下文设置当前的类applicationContext
if (bean instanceof ApplicationContextAware){
((ApplicationContextAware) bean).setApplicationContext(applicationContext);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
- 由于 ApplicationContext 的获取不能直接创建 Bean 的时候就获取到,那么就需要在 refresh 的时候将 ApplicationContext 注册到一个 BeanPostProcessor 中 就可以将其注册到感知类中。
1.2.7.5、注册 BeanPostProcessor
cn.wen.springframework.context.support.AbstractApplicationContext
/**
* @ClassName: AbstractApplicationContext
* @Author: 小飞
* @Date: 2023/3/27 20:19
* @Description:
*/
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
/**
* 执行刷新容器功能
* @throws BeansException
*/
@Override
public void refresh() throws BeansException {
// 1、实现创建bean工厂 BeanFactory 然后加载BeanDefinition
refreshBeanFactory();
// 2、获取BeanFactory
// 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
// 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
// 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 3. 添加 ApplicationContextAwareProcessor,让继承自 ApplicationContextAware 的 Bean 对象都能感知所属的 ApplicationContext
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 4、在Bean实例化之前;执行BeanFactoryPostProcessor 方法中的初始化前和初始化后
invokeBeanFactoryPostProcessors(beanFactory);
// 5、BeanPostProcess 需要提前与其他 Bean对象实例化之前进行注册操作
// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
registerBeanPostProcessors(beanFactory);
// 6、提前实例化单例Bean对象
beanFactory.preInstantiateSingletons();
}
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
Map<String, BeanPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class);
for (BeanPostProcessor beanPostProcessor : beanPostProcessorMap.values()) {
beanFactory.addBeanPostProcessor(beanPostProcessor);
}
}
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
Map<String, BeanFactoryPostProcessor> beanFactoryPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
for (BeanFactoryPostProcessor beanFactoryPostProcessor : beanFactoryPostProcessorMap.values()) {
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
}
}
protected abstract ConfigurableListableBeanFactory getBeanFactory();
protected abstract void refreshBeanFactory();
@Override
public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {
return getBeanFactory().getBeansOfType(type);
}
@Override
public String[] getBeanDefinitionNames() {
return getBeanFactory().getBeanDefinitionNames();
}
@Override
public Object getBean(String name) throws BeansException {
return getBeanFactory().getBean(name);
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
return getBeanFactory().getBean(name, args);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return getBeanFactory().getBean(name, requiredType);
}
@Override
public void registerShutdownHook() {
Runtime.getRuntime().addShutdownHook(new Thread(this::close));
}
@Override
public void close() {
getBeanFactory().destroySingletons();
}
}
1.2.7.6、感知调用操作
cn.wen.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
/**
* @ClassName: AbstractAutowireCapableBeanFactory
* @Author: 小飞
* @Date: 2023/3/26 22:36
* @Description: 继承抽象类AbstractBeanFactory实现相应的抽象方法,实现其中的createBean方法
* 但是AbstractAutowireCapableBeanFactory 本身也是一个抽象类,
* 所以它只会实现属于自己的抽象方法,其他抽象方法由继承 AbstractAutowireCapableBeanFactory 的类实现。
* 这里就体现了类实现过程中的各司其职。
*/
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException {
Object bean = null;
try {
// 实例化 bean
bean = createBeanInstance(beanDefinition, beanName, args);
// 为 bean 对象填充属性
applyPropertyValues(beanName, bean, beanDefinition);
// 执行 Bean 的初始化方法和 BeanPostProcessor 的前置和后置处理方法
bean = initializeBean(beanName, bean, beanDefinition);
} catch (Exception e) {
throw new BeansException("Instantiation of bean failed", e);
}
// 注册实现了 DisposableBean 接口的 Bean 对象
registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);
addSingleton(beanName, bean);
return bean;
}
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, BeanDefinition beanDefinition) {
if (bean instanceof DisposableBean || StrUtil.isNotEmpty(beanDefinition.getDestroyMethodName())) {
registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, beanDefinition));
}
}
// 实例化
protected Object createBeanInstance(BeanDefinition beanDefinition, String beanName, Object[] args) {
Constructor constructorToUse = null;
// 获取当前 Bean 对象的反射类
Class<?> beanClass = beanDefinition.getBeanClass();
// 通过反射类来获取构造函数
Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors();
// 匹配参数的数量
for (Constructor ctor : declaredConstructors) {
if (null != args && ctor.getParameterTypes().length == args.length) {
constructorToUse = ctor;
break;
}
}
// 调用代理接口中的实现类来实现实例化
return getInstantiationStrategy().instantiate(beanDefinition, beanName, constructorToUse, args);
}
/**
* Bean 属性填充
*/
protected void applyPropertyValues(String beanName, Object bean, BeanDefinition beanDefinition) {
try {
PropertyValues propertyValues = beanDefinition.getPropertyValues();
for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
String name = propertyValue.getName();
Object value = propertyValue.getValue();
if (value instanceof BeanReference) {
// A 依赖 B,获取 B 的实例化
BeanReference beanReference = (BeanReference) value;
value = getBean(beanReference.getBeanName());
}
// 属性填充
BeanUtil.setFieldValue(bean, name, value);
}
} catch (Exception e) {
throw new BeansException("Error setting property values:" + beanName);
}
}
public InstantiationStrategy getInstantiationStrategy() {
return instantiationStrategy;
}
public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
this.instantiationStrategy = instantiationStrategy;
}
private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) throws Exception {
// invokeAwareMethods
if (bean instanceof Aware) {
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(this);
}
if (bean instanceof BeanClassLoaderAware){
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
}
// 1. 执行 BeanPostProcessor Before 处理
Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
// 执行 Bean 对象的初始化方法
try {
invokeInitMethods(beanName, wrappedBean, beanDefinition);
} catch (Exception e) {
throw new BeansException("Invocation of init method of bean[" + beanName + "] failed", e);
}
// 2. 执行 BeanPostProcessor After 处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
return wrappedBean;
}
private void invokeInitMethods(String beanName, Object bean, BeanDefinition beanDefinition) throws Exception {
// 1. 实现接口 InitializingBean 判断是否实现了初始化接口
if (bean instanceof InitializingBean) {
((InitializingBean) bean).afterPropertiesSet();
}
// 2. 注解配置 init-method {判断是为了避免二次执行初始化}
String initMethodName = beanDefinition.getInitMethodName();
if (StrUtil.isNotEmpty(initMethodName) && !(bean instanceof InitializingBean)) {
Method initMethod = beanDefinition.getBeanClass().getMethod(initMethodName);
if (null == initMethod) {
throw new BeansException("Could not find an init method named '" + initMethodName + "' on bean with name '" + beanName + "'");
}
initMethod.invoke(bean);
}
}
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (null == current) return result;
result = current;
}
return result;
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (null == current) return result;
result = current;
}
return result;
}
}
那么里面还有一个获取类加载器的方法哪里来?
通过 AbstractAutowireCapableBeanFactory 的父类 AbstractBeanFactory 提供
cn.wen.springframework.beans.factory.support.AbstractBeanFactory
/**
* @ClassName: AbstractBeanFactory
* @Author: 小飞
* @Date: 2023/3/26 22:46
* @Description:
*/
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements ConfigurableBeanFactory {
// 提供当前线程的类加载器
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
// 后置处理器列表
private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<BeanPostProcessor>();
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null);
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
return doGetBean(name, args);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return (T) getBean(name);
}
protected <T> T doGetBean(final String name, final Object[] args) {
// 获取父类DefaultSingletonBeanRegistry中单例池中的单例对象
Object bean = getSingleton(name);
if (bean != null) {
return (T) bean;
}
// 如果为空说明需要创建一个 Bean 对象那么就需要拿到对应的BeanDefinition对象存储了相关元数据
BeanDefinition beanDefinition = getBeanDefinition(name);
// 通过 beanName、BeanDefinition 来创建一个Bean对象但是这里只定义抽象方法由实现类来实现具体创建流程。
return (T) createBean(name, beanDefinition, args);
}
protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
protected abstract Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException;
@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor){
this.beanPostProcessors.remove(beanPostProcessor);
this.beanPostProcessors.add(beanPostProcessor);
}
// 获取全部的后置处理器
public List<BeanPostProcessor> getBeanPostProcessors() {
return this.beanPostProcessors;
}
public ClassLoader getBeanClassLoader() {
return this.beanClassLoader;
}
}
1.2.7.7、测试
cn.wen.springframework.test.bean.UserDao
public class UserDao {
// 模拟数据库操作
private static Map<String, String> hashMap = new HashMap<>();
public void initDataMethod(){
System.out.println("执行:init-method");
hashMap.put("10001", "小飞");
hashMap.put("10002", "小飞飞");
hashMap.put("10003", "小飞飞");
}
public void destroyDataMethod(){
System.out.println("执行:destroy-method");
hashMap.clear();
}
public String queryUserName(String id) {
return hashMap.get(id);
}
}
cn.wen.springframework.test.bean.UserService
/**
* @ClassName: UserService
* @Author: 小飞
* @Date: 2023/3/26 23:10
* @Description: 待注册类
*/
public class UserService implements BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware {
private ApplicationContext applicationContext;
private BeanFactory beanFactory;
private String id;
private String company;
private String location;
private UserDao userDao;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void setBeanName(String name) {
System.out.println("Bean Name is:" + name);
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("ClassLoader:" + classLoader);
}
public String queryUserInfo() {
return userDao.queryUserName(id) + "," + company + "," + location;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public ApplicationContext getApplicationContext() {
return applicationContext;
}
public BeanFactory getBeanFactory() {
return beanFactory;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="userDao" class="cn.wen.springframework.test.bean.UserDao" init-method="initDataMethod" destroy-method="destroyDataMethod"/>
<bean id="userService" class="cn.wen.springframework.test.bean.UserService">
<property name="id" value="10001"/>
<property name="company" value="腾讯"/>
<property name="location" value="深圳"/>
<property name="userDao" ref="userDao"/>
</bean>
</beans>
@Test
public void test_xml() {
// 1.初始化 BeanFactory
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
applicationContext.registerShutdownHook();
// 2. 获取Bean对象调用方法
UserService userService = applicationContext.getBean("userService", UserService.class);
String result = userService.queryUserInfo();
System.out.println("测试结果:" + result);
System.out.println("ApplicationContextAware:"+userService.getApplicationContext());
System.out.println("BeanFactoryAware:"+userService.getBeanFactory());
}
1.2.8、对象作用域和FactoryBean
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-29OmQk4t-1690811375716)(https://cdn.nlark.com/yuque/0/2023/png/25484710/1680005797130-f622f045-7fe9-489d-a8a3-1d259bb9f4f4.png#averageHue=%23fcfcfc&clientId=u71e01f5c-571e-4&from=paste&height=655&id=ubbf687a4&originHeight=983&originWidth=962&originalType=binary&ratio=1.25&rotation=0&showTitle=false&size=65850&status=done&style=none&taskId=u3be1959c-a754-4e93-8e40-0c43942eebb&title=&width=641.3333333333334)]
- 整个实现过程包括解决单例还是原型对象,处理FactoryBean 类型对象创建过程中获取具体对象的 getObject 操作。
- SCOPE_SINGLETON、SCOPE_PROTOTYPE,对象类型的创建获取方式,主要区分在于 AbstractAutowireCapableBeanFactory#createBean 创建完成对象后是否放入到内存中,如果不放入则每次获取都会重新创建。
- createBean 执行对象创建、属性填充、依赖加载、前置后置处理、初始化等操作后,就要开始做执行判断整个对象是否是一个 FactoryBean 对象,如果是这样的对象,就需要再继续执行获取 FactoryBean 具体对象中的 getObject 对象了。整个 getBean 过程中都会新增一个单例类型的判断factory.isSingleton(),用于决定是否使用内存存放对象信息。
1.2.8.1、工程结构
│
├─src
│ ├─main
│ │ ├─java
│ │ │ └─cn
│ │ │ └─wen
│ │ │ └─springframework
│ │ │ ├─beans
│ │ │ │ │ BeansException.java
│ │ │ │ │ PropertyValue.java
│ │ │ │ │ PropertyValues.java
│ │ │ │ │
│ │ │ │ └─factory
│ │ │ │ │ Aware.java
│ │ │ │ │ BeanClassLoaderAware.java
│ │ │ │ │ BeanFactory.java
│ │ │ │ │ BeanFactoryAware.java
│ │ │ │ │ BeanNameAware.java
│ │ │ │ │ ConfigurableListableBeanFactory.java
│ │ │ │ │ DisposableBean.java
│ │ │ │ │ FactoryBean.java #
│ │ │ │ │ HierarchicalBeanFactory.java
│ │ │ │ │ InitializingBean.java
│ │ │ │ │ ListableBeanFactory.java
│ │ │ │ │
│ │ │ │ ├─config
│ │ │ │ │ AutowireCapableBeanFactory.java
│ │ │ │ │ BeanDefinition.java
│ │ │ │ │ BeanFactoryPostProcessor.java
│ │ │ │ │ BeanPostProcessor.java
│ │ │ │ │ BeanReference.java
│ │ │ │ │ ConfigurableBeanFactory.java
│ │ │ │ │ SingletonBeanRegistry.java
│ │ │ │ │
│ │ │ │ ├─support
│ │ │ │ │ AbstractAutowireCapableBeanFactory.java #
│ │ │ │ │ AbstractBeanDefinitionReader.java
│ │ │ │ │ AbstractBeanFactory.java #
│ │ │ │ │ BeanDefinitionReader.java
│ │ │ │ │ BeanDefinitionRegistry.java
│ │ │ │ │ CglibSubclassingInstantiationStrategy.java
│ │ │ │ │ DefaultListableBeanFactory.java
│ │ │ │ │ DefaultSingletonBeanRegistry.java #
│ │ │ │ │ DisposableBeanAdapter.java
│ │ │ │ │ FactoryBeanRegistrySupport.java #
│ │ │ │ │ InstantiationStrategy.java
│ │ │ │ │ SimpleInstantiationStrategy.java
│ │ │ │ │
│ │ │ │ └─xml
│ │ │ │ XmlBeanDefinitionReader.java #
│ │ │ │
│ │ │ ├─context
│ │ │ │ │ ApplicationContext.java
│ │ │ │ │ ApplicationContextAware.java
│ │ │ │ │ ConfigurableApplicationContext.java
│ │ │ │ │
│ │ │ │ └─support
│ │ │ │ AbstractApplicationContext.java
│ │ │ │ AbstractRefreshableApplicationContext.java
│ │ │ │ AbstractXmlApplicationContext.java
│ │ │ │ ApplicationContextAwareProcessor.java
│ │ │ │ ClassPathXmlApplicationContext.java
│ │ │ │
│ │ │ ├─core
│ │ │ │ └─io
│ │ │ │ ClassPathResource.java
│ │ │ │ DefaultResourceLoader.java
│ │ │ │ FileSystemResource.java
│ │ │ │ Resource.java
│ │ │ │ ResourceLoader.java
│ │ │ │ UrlResource.java
│ │ │ │
│ │ │ └─util
│ │ │ ClassUtils.java
│ │
│ └─test
│ ├─java
│ │ └─cn
│ │ └─wen
│ │ └─springframework
│ │ └─test
│ │ │ ApiTest.java #
│ │ │
│ │ ├─bean
│ │ │ IUserDao.java #
│ │ │ ProxyBeanFactory.java #
│ │ │ UserService.java #
│ │
│ └─resources
│ spring.xml #
│
- 类关系图展示的就是添加 Bean 的实例化是单例还是原型模式以及 FactoryBean 的实现。
- 只是在现有的 AbstractAutowireCapableBeanFactory 类以及继承的抽象类 AbstractBeanFactory 中进行扩展。
- 我们把 AbstractBeanFactory 继承的 DefaultSingletonBeanRegistry 类,中间加了一层 FactoryBeanRegistrySupport,这个类在 Spring 框架中主要是处理关于 FactoryBean 注册的支撑操作。
1.2.8.2、BeanDefinition作用域定义和xml解析
cn.wen.springframework.beans.factory.config.BeanDefinition
/**
* @ClassName: BeanDefinition
* @Author: 小飞
* @Date: 2023/3/25 21:06
* @Description: 用于保存Bean的相关信息,包括属性、构造方法参数、
* 依赖的Bean名称及是否单例、延迟加载等,它是实例化 Bean 的原材料,存储Bean初始化时的元数据
* Spring就是根据BeanDefinition中的信息实例化 Bean。
*/
public class BeanDefinition {
// scope类型:单例类型
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
// scope类型:原型类型
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
// 当前bean对象的class类型
private Class beanClass;
// 当前bean对象的属性列表
private PropertyValues propertyValues;
// 初始化方法名称
private String initMethodName;
// 销毁方法名称
private String destroyMethodName;
// scope类型默认类型:单例类型
private String scope = SCOPE_SINGLETON;
private boolean singleton = true;
private boolean prototype = false;
public BeanDefinition(Class beanClass) {
this(beanClass, null);
}
public BeanDefinition(Class beanClass, PropertyValues propertyValues) {
this.beanClass = beanClass;
this.propertyValues = propertyValues != null ? propertyValues : new PropertyValues();
}
public void setScope(String scope) {
this.scope = scope;
this.singleton = SCOPE_SINGLETON.equals(scope);
this.prototype = SCOPE_PROTOTYPE.equals(scope);
}
public boolean isSingleton() {
return singleton;
}
public boolean isPrototype() {
return prototype;
}
public Class getBeanClass() {
return beanClass;
}
public void setBeanClass(Class beanClass) {
this.beanClass = beanClass;
}
public PropertyValues getPropertyValues() {
return propertyValues;
}
public void setPropertyValues(PropertyValues propertyValues) {
this.propertyValues = propertyValues;
}
public String getInitMethodName() {
return initMethodName;
}
public void setInitMethodName(String initMethodName) {
this.initMethodName = initMethodName;
}
public String getDestroyMethodName() {
return destroyMethodName;
}
public void setDestroyMethodName(String destroyMethodName) {
this.destroyMethodName = destroyMethodName;
}
}
- singleton、prototype,是本次在 BeanDefinition 类中新增加的两个属性信息,用于把从 spring.xml 中解析到的 Bean 对象作用范围填充到属性中。
cn.wen.springframework.beans.factory.xml.XmlBeanDefinitionReader
/**
* @ClassName: XmlBeanDefinitionReader
* @Author: 小飞
* @Date: 2023/3/27 17:44
* @Description: xml 文件解析器
*/
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
super(registry);
}
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry, ResourceLoader resourceLoader) {
super(registry, resourceLoader);
}
@Override
public void loadBeanDefinitions(Resource resource) throws BeansException {
try {
try (InputStream inputStream = resource.getInputStream()) {
doLoadBeanDefinitions(inputStream);
}
} catch (IOException | ClassNotFoundException e) {
throw new BeansException("IOException parsing XML document from " + resource, e);
}
}
@Override
public void loadBeanDefinitions(Resource... resources) throws BeansException {
for (Resource resource : resources) {
loadBeanDefinitions(resource);
}
}
@Override
public void loadBeanDefinitions(String location) throws BeansException {
ResourceLoader resourceLoader = getResourceLoader();
Resource resource = resourceLoader.getResource(location);
loadBeanDefinitions(resource);
}
@Override
public void loadBeanDefinitions(String... locations) throws BeansException {
for (String location : locations) {
loadBeanDefinitions(location);
}
}
protected void doLoadBeanDefinitions(InputStream inputStream) throws ClassNotFoundException {
Document doc = XmlUtil.readXML(inputStream);
Element root = doc.getDocumentElement();
NodeList childNodes = root.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
// 判断元素
if (!(childNodes.item(i) instanceof Element)) continue;
// 判断对象
if (!"bean".equals(childNodes.item(i).getNodeName())) continue;
// 解析标签
Element bean = (Element) childNodes.item(i);
String id = bean.getAttribute("id");
String name = bean.getAttribute("name");
String className = bean.getAttribute("class");
String initMethod = bean.getAttribute("init-method");
String destroyMethodName = bean.getAttribute("destroy-method");
String beanScope = bean.getAttribute("scope");
// 获取 Class,方便获取类中的名称
Class<?> clazz = Class.forName(className);
// 优先级 id > name
String beanName = StrUtil.isNotEmpty(id) ? id : name;
if (StrUtil.isEmpty(beanName)) {
beanName = StrUtil.lowerFirst(clazz.getSimpleName());
}
// 定义Bean
BeanDefinition beanDefinition = new BeanDefinition(clazz);
beanDefinition.setInitMethodName(initMethod);
beanDefinition.setDestroyMethodName(destroyMethodName);
if (StrUtil.isNotEmpty(beanScope)) {
beanDefinition.setScope(beanScope);
}
// 读取属性并填充
for (int j = 0; j < bean.getChildNodes().getLength(); j++) {
if (!(bean.getChildNodes().item(j) instanceof Element)) continue;
if (!"property".equals(bean.getChildNodes().item(j).getNodeName())) continue;
// 解析标签:property
Element property = (Element) bean.getChildNodes().item(j);
String attrName = property.getAttribute("name");
String attrValue = property.getAttribute("value");
String attrRef = property.getAttribute("ref");
// 获取属性值:引入对象、值对象
Object value = StrUtil.isNotEmpty(attrRef) ? new BeanReference(attrRef) : attrValue;
// 创建属性信息
PropertyValue propertyValue = new PropertyValue(attrName, value);
beanDefinition.getPropertyValues().addPropertyValue(propertyValue);
}
if (getRegistry().containsBeanDefinition(beanName)) {
throw new BeansException("Duplicate beanName[" + beanName + "] is not allowed");
}
// 注册 BeanDefinition
getRegistry().registerBeanDefinition(beanName, beanDefinition);
}
}
}
1.2.8.3、创建和修改对象时判断单例还是原型
cn.wen.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
/**
* @ClassName: AbstractAutowireCapableBeanFactory
* @Author: 小飞
* @Date: 2023/3/26 22:36
* @Description: 继承抽象类AbstractBeanFactory实现相应的抽象方法,实现其中的createBean方法
* 但是AbstractAutowireCapableBeanFactory 本身也是一个抽象类,
* 所以它只会实现属于自己的抽象方法,其他抽象方法由继承 AbstractAutowireCapableBeanFactory 的类实现。
* 这里就体现了类实现过程中的各司其职。
*/
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException {
Object bean = null;
try {
// 实例化 bean
bean = createBeanInstance(beanDefinition, beanName, args);
// 为 bean 对象填充属性
applyPropertyValues(beanName, bean, beanDefinition);
// 执行 Bean 的初始化方法和 BeanPostProcessor 的前置和后置处理方法
bean = initializeBean(beanName, bean, beanDefinition);
} catch (Exception e) {
throw new BeansException("Instantiation of bean failed", e);
}
// 注册实现了 DisposableBean 接口的 Bean 对象
registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);
// 判断 SCOPE_SINGLETON、SCOPE_PROTOTYPE
if (beanDefinition.isSingleton()) {
addSingleton(beanName, bean);
}
return bean;
}
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, BeanDefinition beanDefinition) {
// 非 Singleton 类型的 Bean 不执行销毁方法
if (!beanDefinition.isSingleton()) return;
if (bean instanceof DisposableBean || StrUtil.isNotEmpty(beanDefinition.getDestroyMethodName())) {
registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, beanDefinition));
}
}
// 实例化
protected Object createBeanInstance(BeanDefinition beanDefinition, String beanName, Object[] args) {
Constructor constructorToUse = null;
// 获取当前 Bean 对象的反射类
Class<?> beanClass = beanDefinition.getBeanClass();
// 通过反射类来获取构造函数
Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors();
// 匹配参数的数量
for (Constructor ctor : declaredConstructors) {
if (null != args && ctor.getParameterTypes().length == args.length) {
constructorToUse = ctor;
break;
}
}
// 调用代理接口中的实现类来实现实例化
return getInstantiationStrategy().instantiate(beanDefinition, beanName, constructorToUse, args);
}
/**
* Bean 属性填充
*/
protected void applyPropertyValues(String beanName, Object bean, BeanDefinition beanDefinition) {
try {
PropertyValues propertyValues = beanDefinition.getPropertyValues();
for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
String name = propertyValue.getName();
Object value = propertyValue.getValue();
if (value instanceof BeanReference) {
// A 依赖 B,获取 B 的实例化
BeanReference beanReference = (BeanReference) value;
value = getBean(beanReference.getBeanName());
}
// 属性填充
BeanUtil.setFieldValue(bean, name, value);
}
} catch (Exception e) {
throw new BeansException("Error setting property values:" + beanName);
}
}
public InstantiationStrategy getInstantiationStrategy() {
return instantiationStrategy;
}
public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
this.instantiationStrategy = instantiationStrategy;
}
private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) throws Exception {
// invokeAwareMethods
if (bean instanceof Aware) {
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(this);
}
if (bean instanceof BeanClassLoaderAware){
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
}
// 1. 执行 BeanPostProcessor Before 处理
Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
// 执行 Bean 对象的初始化方法
try {
invokeInitMethods(beanName, wrappedBean, beanDefinition);
} catch (Exception e) {
throw new BeansException("Invocation of init method of bean[" + beanName + "] failed", e);
}
// 2. 执行 BeanPostProcessor After 处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
return wrappedBean;
}
private void invokeInitMethods(String beanName, Object bean, BeanDefinition beanDefinition) throws Exception {
// 1. 实现接口 InitializingBean 判断是否实现了初始化接口
if (bean instanceof InitializingBean) {
((InitializingBean) bean).afterPropertiesSet();
}
// 2. 注解配置 init-method {判断是为了避免二次执行初始化}
String initMethodName = beanDefinition.getInitMethodName();
if (StrUtil.isNotEmpty(initMethodName) && !(bean instanceof InitializingBean)) {
Method initMethod = beanDefinition.getBeanClass().getMethod(initMethodName);
if (null == initMethod) {
throw new BeansException("Could not find an init method named '" + initMethodName + "' on bean with name '" + beanName + "'");
}
initMethod.invoke(bean);
}
}
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (null == current) return result;
result = current;
}
return result;
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (null == current) return result;
result = current;
}
return result;
}
}
- 单例模式和原型模式的区别就在于是否存放到内存中,如果是原型模式那么就不会存放到内存中,每次获取都重新创建对象,另外非 Singleton 类型的 Bean 不需要执行销毁方法。
- 所以这里的代码会有两处修改,一处是 createBean 中判断是否添加到 addSingleton(beanName, bean);,另外一处是 registerDisposableBeanIfNecessary 销毁注册中的判断 if (!beanDefinition.isSingleton()) return;。
1.2.8.4、定义 FactoryBean 接口
cn.wen.springframework.beans.factory.FactoryBean
/**
* @ClassName: FactoryBean
* @Author: 小飞
* @Date: 2023/3/28 20:24
* @Description: 通常创建比较复杂的Bean,一般的Bean可以通过xml来配置,但是一个bean的创建过程涉及到了
* 其他的bean和复杂的逻辑,就可以使用 FactoryBean
*/
public interface FactoryBean<T> {
T getObject() throws Exception;
Class<?> getObjectType();
boolean isSingleton();
}
- 通常创建比较复杂的Bean,一般的Bean可以通过xml来配置,但是一个bean的创建过程涉及到了其他的bean和复杂的逻辑,就可以使用 FactoryBean
1.2.8.5、实现 FactoryBean 注册服务
cn.wen.springframework.beans.factory.support.FactoryBeanRegistrySupport
/**
* @ClassName: FactoryBeanRegistrySupport
* @Author: 小飞
* @Date: 2023/3/28 20:32
* @Description: 管理和创建 FactoryBean 产生的单例对象
*/
public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry {
// 缓存factoryBeans创建的singleton对象
private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<String, Object>();
//从 缓存中获取指定的beanName的对象如果是NULL_OBJECT则返回null
protected Object getCachedObjectForFactoryBean(String beanName) {
Object object = this.factoryBeanObjectCache.get(beanName);
return (object != NULL_OBJECT ? object : null);
}
protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName) {
// 是否为单例 如果FactoryBean 单例池中存在 则直接返回
if (factory.isSingleton()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName);
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
}
return (object != NULL_OBJECT ? object : null);
} else {
// 不为单例则创建
return doGetObjectFromFactoryBean(factory, beanName);
}
}
// 通过 FactoryBean 获取对象
private Object doGetObjectFromFactoryBean(final FactoryBean factory, final String beanName){
try {
// 通过实现类去实现复杂的创建Bean对象过程
return factory.getObject();
} catch (Exception e) {
throw new BeansException("FactoryBean threw exception on object[" + beanName + "] creation", e);
}
}
}
- FactoryBeanRegistrySupport 类主要经济 FactoryBean 对象的创建,可以实现不同的领域只需要负责完成各自需要的功能,避免扩展导致类膨胀。
- 定义了 缓存操作 factoryBeanObjectCache 用来存放单例类型的对象,避免重复创建。
- doGetObjectFromFactoryBean 是具体的获取 FactoryBean#getObject() 方法。
1.2.8.6、扩展 AbstractBeanFactory 创建对象
cn.wen.springframework.beans.factory.support.AbstractBeanFactory
/**
* @ClassName: AbstractBeanFactory
* @Author: 小飞
* @Date: 2023/3/26 22:46
* @Description:
*/
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
// 提供当前线程的类加载器
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
// 后置处理器列表
private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<BeanPostProcessor>();
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null);
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
return doGetBean(name, args);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return (T) getBean(name);
}
protected <T> T doGetBean(final String name, final Object[] args) {
// 获取父类DefaultSingletonBeanRegistry中单例池中的单例对象
Object sharedInstance = getSingleton(name);
if (sharedInstance != null) {
// 如果是 FactoryBean,则需要调用 FactoryBean#getObject
return (T) getObjectForBeanInstance(sharedInstance, name);
}
// 如果为空说明需要创建一个 Bean 对象那么就需要拿到对应的BeanDefinition对象存储了相关元数据
BeanDefinition beanDefinition = getBeanDefinition(name);
// 通过 beanName、BeanDefinition 来创建一个Bean对象但是这里只定义抽象方法由实现类来实现具体创建流程。
Object bean = createBean(name, beanDefinition, args);
return (T) getObjectForBeanInstance(bean, name);
}
private Object getObjectForBeanInstance(Object beanInstance, String beanName) {
// 如果该对象不为 FactoryBean 则直接返回
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
// 如果该对象为 FactoryBean 那么先看缓存中是否 存在 如果不存在则创建FactoryBean对象
Object object = getCachedObjectForFactoryBean(beanName);
if (object == null) {
FactoryBean<?> factoryBean = (FactoryBean<?>) beanInstance;
object = getObjectFromFactoryBean(factoryBean, beanName);
}
return object;
}
protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
protected abstract Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException;
@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor){
this.beanPostProcessors.remove(beanPostProcessor);
this.beanPostProcessors.add(beanPostProcessor);
}
// 获取全部的后置处理器
public List<BeanPostProcessor> getBeanPostProcessors() {
return this.beanPostProcessors;
}
public ClassLoader getBeanClassLoader() {
return this.beanClassLoader;
}
}
- AbstractBeanFactory 原来继承的 DefaultSingletonBeanRegistry,修改为继承 FactoryBeanRegistrySupport。因为需要扩展出创建 FactoryBean 对象的能力,所以这就想一个链条服务上,截出一个段来处理额外的服务,并把链条再链接上。
- 新增 doGetBean 方法中,添加调用(T) getObjectForBeanInstance(sharedInstance, name) 对获取 FactoryBean 的操作。
- 在 getObjectForBeanInstance 方法中做具体的 instanceof 判断,另外还会从 FactoryBean 的缓存中获取对象,如果不存在则调用 FactoryBeanRegistrySupport#getObjectFromFactoryBean,执行具体的操作。
- 在返回 Bean 的 需要通过beanInstance instanceof FactoryBean 判断是否为 FactoryBean 类型,如果通过 getObjectForBeanInstance 方法中的判断 不为 FactoryBean的类型就可以直接返回 BeanFactory 生成的Bean对象,如果判断是,则需要在 FactoryBean 缓冲池中获取或者通过 factory.getObject(); (还需要判断是否单例,创建的对象是否需要存放缓存中)通过实现类来获取该 Bean 对象。
1.2.8.7、测试
cn.wen.springframework.test.bean.IUserDao
/**
* @ClassName: IUserDao
* @Author: 小飞
* @Date: 2023/3/28 20:48
* @Description:
*/
public interface IUserDao {
String queryUserName(String id);
}
cn.wen.springframework.test.bean.ProxyBeanFactory
/**
* @ClassName: ProxyBeanFactory
* @Author: 小飞
* @Date: 2023/3/28 20:49
* @Description: FactoryBean 接口的实现类
*/
public class ProxyBeanFactory implements FactoryBean<IUserDao> {
@Override
public IUserDao getObject() throws Exception {
InvocationHandler handler = (proxy, method, args) -> {
// 添加排除方法
if ("toString".equals(method.getName())) return this.toString();
Map<String, String> hashMap = new HashMap<>();
hashMap.put("10001", "小阿飞");
hashMap.put("10002", "阿飞");
hashMap.put("10003", "小小");
return "你被代理了 " + method.getName() + ":" + hashMap.get(args[0].toString());
};
return (IUserDao) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{IUserDao.class}, handler);
}
@Override
public Class<?> getObjectType() {
return IUserDao.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
- 取代了UserDao 实现了 FactoryBean 来实现复杂的配置
cn.wen.springframework.test.bean.UserService
/**
* @ClassName: UserService
* @Author: 小飞
* @Date: 2023/3/26 23:10
* @Description: 待注册类
*/
public class UserService {
private String id;
private String company;
private String location;
private IUserDao userDao;
public String queryUserInfo() {
return userDao.queryUserName(id) + "," + company + "," + location;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public IUserDao getUserDao() {
return userDao;
}
public void setUserDao(IUserDao userDao) {
this.userDao = userDao;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="userService" class="cn.wen.springframework.test.bean.UserService" scope="prototype">
<property name="id" value="10001"/>
<property name="company" value="腾讯"/>
<property name="location" value="深圳"/>
<property name="userDao" ref="proxyUserDao"/>
</bean>
<bean id="proxyUserDao" class="cn.wen.springframework.test.bean.ProxyBeanFactory"/>
</beans>
@Test
public void test_prototype() {
// 1.初始化 BeanFactory
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
applicationContext.registerShutdownHook();
// 2. 获取Bean对象调用方法
UserService userService01 = applicationContext.getBean("userService", UserService.class);
UserService userService02 = applicationContext.getBean("userService", UserService.class);
// 3. 配置 scope="prototype/singleton"
System.out.println(userService01);
System.out.println(userService02);
// 4. 打印十六进制哈希
System.out.println(userService01 + " 十六进制哈希:" + Integer.toHexString(userService01.hashCode()));
System.out.println(ClassLayout.parseInstance(userService01).toPrintable());
}
@Test
public void test_factory_bean() {
// 1.初始化 BeanFactory
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
applicationContext.registerShutdownHook();
// 2. 调用代理方法
UserService userService = applicationContext.getBean("userService", UserService.class);
System.out.println("测试结果:" + userService.queryUserInfo());
}
1.2.9、容器事件和事件监听器
在 Spring 中有一个 Event 事件功能,它可以提供事件的定义、发布以及监听事件来完成一些自定义的动作。比如你可以定义一个新用户注册的事件,当有用户执行注册完成后,在事件监听中给用户发送一些优惠券和短信提醒,这样的操作就可以把属于基本功能的注册和对应的策略服务分开,降低系统的耦合。以后在扩展注册服务,比如需要添加风控策略、添加实名认证、判断用户属性等都不会影响到依赖注册成功后执行的动作。
我们需要以观察者模式的方式,设计和实现 Spring Event 的容器事件和事件监听器功能,最终可以让我们在现有实现的 Spring 框架中可以定义、监听和发布自己的事件信息。
其实事件的设计本身就是一种观察者模式的实现,它所要解决的就是一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
在功能实现上我们需要定义出事件类、事件监听、事件发布,而这些类的功能需要结合到 Spring 的 AbstractApplicationContext#refresh(),以便于处理事件初始化和注册事件监听器的操作。
整体设计结构如下图:
- 需要在 AbstractApplicationContext 中添加监听相关代码块,包括:初始化事件发布者、注册事件监听器、发布容器刷新完成事件。
- 使用观察者模式定义事件类、监听类、发布类,同时还需要完成一个广播器的功能,接收到事件推送时进行分析处理符合监听事件接受者感兴趣的事件,也就是使用 isAssignableFrom 进行判断。
- isAssignableFrom 和 instanceof 相似,不过 isAssignableFrom 是用来判断子类和父类的关系的,或者接口的实现类和接口的关系的,默认所有的类的终极父类都是Object。如果A.isAssignableFrom(B)结果是true,证明B可以转换成为A,也就是A可以由B转换而来。
1.2.9.1、工程结构
│
├─src
│ ├─main
│ │ ├─java
│ │ │ └─cn
│ │ │ └─wen
│ │ │ └─springframework
│ │ │ ├─beans
│ │ │ │ │ BeansException.java
│ │ │ │ │ PropertyValue.java
│ │ │ │ │ PropertyValues.java
│ │ │ │ │
│ │ │ │ └─factory
│ │ │ │ │ Aware.java
│ │ │ │ │ BeanClassLoaderAware.java
│ │ │ │ │ BeanFactory.java
│ │ │ │ │ BeanFactoryAware.java
│ │ │ │ │ BeanNameAware.java
│ │ │ │ │ ConfigurableListableBeanFactory.java
│ │ │ │ │ DisposableBean.java
│ │ │ │ │ FactoryBean.java
│ │ │ │ │ HierarchicalBeanFactory.java #
│ │ │ │ │ InitializingBean.java
│ │ │ │ │ ListableBeanFactory.java
│ │ │ │ │
│ │ │ │ ├─config
│ │ │ │ │ AutowireCapableBeanFactory.java
│ │ │ │ │ BeanDefinition.java
│ │ │ │ │ BeanFactoryPostProcessor.java
│ │ │ │ │ BeanPostProcessor.java
│ │ │ │ │ BeanReference.java
│ │ │ │ │ ConfigurableBeanFactory.java
│ │ │ │ │ SingletonBeanRegistry.java
│ │ │ │ │
│ │ │ │ ├─support
│ │ │ │ │ AbstractAutowireCapableBeanFactory.java
│ │ │ │ │ AbstractBeanDefinitionReader.java
│ │ │ │ │ AbstractBeanFactory.java
│ │ │ │ │ BeanDefinitionReader.java
│ │ │ │ │ BeanDefinitionRegistry.java
│ │ │ │ │ CglibSubclassingInstantiationStrategy.java
│ │ │ │ │ DefaultListableBeanFactory.java
│ │ │ │ │ DefaultSingletonBeanRegistry.java
│ │ │ │ │ DisposableBeanAdapter.java
│ │ │ │ │ FactoryBeanRegistrySupport.java
│ │ │ │ │ InstantiationStrategy.java
│ │ │ │ │ SimpleInstantiationStrategy.java
│ │ │ │ │
│ │ │ │ └─xml
│ │ │ │ XmlBeanDefinitionReader.java
│ │ │ │
│ │ │ ├─context
│ │ │ │ │ ApplicationContext.java #
│ │ │ │ │ ApplicationContextAware.java
│ │ │ │ │ ApplicationEvent.java #
│ │ │ │ │ ApplicationEventPublisher.java #
│ │ │ │ │ ApplicationListener.java #
│ │ │ │ │ ConfigurableApplicationContext.java
│ │ │ │ │
│ │ │ │ ├─event
│ │ │ │ │ AbstractApplicationEventMulticaster.java #
│ │ │ │ │ ApplicationContextEvent.java #
│ │ │ │ │ ApplicationEventMulticaster.java #
│ │ │ │ │ ContextClosedEvent.java #
│ │ │ │ │ ContextRefreshedEvent.java #
│ │ │ │ │ SimpleApplicationEventMulticaster.java #
│ │ │ │ │
│ │ │ │ └─support
│ │ │ │ AbstractApplicationContext.java #
│ │ │ │ AbstractRefreshableApplicationContext.java
│ │ │ │ AbstractXmlApplicationContext.java
│ │ │ │ ApplicationContextAwareProcessor.java
│ │ │ │ ClassPathXmlApplicationContext.java
│ │ │ │
│ │ │ ├─core
│ │ │ │ └─io
│ │ │ │ ClassPathResource.java
│ │ │ │ DefaultResourceLoader.java
│ │ │ │ FileSystemResource.java
│ │ │ │ Resource.java
│ │ │ │ ResourceLoader.java
│ │ │ │ UrlResource.java
│ │ │ │
│ │ │ └─util
│ │ │ ClassUtils.java
│ │
│ └─test
│ ├─java
│ │ └─cn
│ │ └─wen
│ │ └─springframework
│ │ └─test
│ │ │ ApiTest.java #
│ │ │
│ │ └─event
│ │ ContextClosedEventListener.java #
│ │ ContextRefreshedEventListener.java #
│ │ CustomEvent.java #
│ │ CustomEventListener.java #
│ │
│ └─resources
│ spring.xml
│
整个类关系图以围绕实现 event 事件定义、发布、监听功能实现和把事件的相关内容使用 AbstractApplicationContext#refresh 进行注册和处理操作。
- EventObject:Java提供的工具类,传递事件信息。
- ApplicationEvent:提供的一套集事件注册、监听、触发为一体的事件实现。可以实现事件封装。事件容器
- ApplicationContextEvent:提供实现 ApplicationContext ,如果容器中有一个 ApplicationListener Bean 每当 ApplicationContext 发布 ApplicationEvent时,ApplicationListener Bean将自动触发。
- ContextRefreshedEvent:事件发生在容器初始化完毕之后, Spring 已经将所有的 bean 成功加载,我们在这个监听器注入我们要用到的 bean 后 完成启动的初始化任务。重新刷新预加载的资源。
- ContextCloseEvent:上下文给你监听事件
- ApplicationContext:增加 ApplicationEventPublisher 继承接口
- ApplicationEventPublisher:事件发布者接口
- ApplicationEventMulticaster:事件监听器的一系列操作相当于事件的管理器
- AbstractApplicationEventMulticaster:承 BeanFactoryAware 就是为了获取 BeanFactory 对象实现了 ApplicationEventMulticaster 接口就是管理事件监听的核心类,存储了全部的监听事件对象同时实现了监听事件的添加、移除、获取全部监听事件、判断当前Bean对象是否设置了监听
- SimpleApplicationEventMulticaster:事件广播的实现类
- AbstractApplicationContext:修改 refresh 方法的流程,增加事件的代码块,包括初始化事件发布者、注册事件监听器、发布容器刷新事件。
- HierarchicalBeanFactory:将接口方法全部清除,目前还用不到。
1.2.9.2、定义和实现事件
cn.wen.springframework.context.ApplicationEvent
/**
* @ClassName: ApplicationEvent
* @Author: 小飞
* @Date: 2023/3/28 22:11
* @Description: 提供 一套集事件注册、监听、触发为一体的事件实现 监听上下文
*/
public abstract class ApplicationEvent extends EventObject {
public ApplicationEvent(Object source) {
super(source);
}
}
- 以继承 java.util.EventObject 定义出具备事件功能的抽象类 ApplicationEvent,后续所有事件的类都需要继承这个类。
cn.wen.springframework.context.event.ApplicationContextEvent
/**
* @ClassName: ApplicationContextEvent
* @Author: 小飞
* @Date: 2023/3/28 22:16
* @Description: 监听事件应用上下文
*/
public class ApplicationContextEvent extends ApplicationEvent {
public ApplicationContextEvent(Object source) {
super(source);
}
public final ApplicationContext getApplicationContext() {
return (ApplicationContext) getSource();
}
}
cn.wen.springframework.context.event.ContextCloseEvent
/**
* @ClassName: ContextCloseEvent
* @Author: 小飞
* @Date: 2023/3/28 22:22
* @Description: 关闭事件监听的实现类
*/
public class ContextClosedEvent extends ApplicationContextEvent{
public ContextClosedEvent(Object source) {
super(source);
}
}
cn.wen.springframework.context.event.ContextRefreshedEvent
/**
* @ClassName: ContextRefreshedEvent
* @Author: 小飞
* @Date: 2023/3/28 22:24
* @Description: 容器重新刷新事件
*/
public class ContextRefreshedEvent extends ApplicationContextEvent{
public ContextRefreshedEvent(Object source) {
super(source);
}
}
- ApplicationContextEvent 是定义事件的抽象类,所有的事件包括关闭、刷新,以及用户自己实现的事件,都需要继承这个类。
- ContextClosedEvent、ContextRefreshedEvent,分别是 Spring 框架自己实现的两个事件类,可以用于监听刷新和关闭动作。
1.2.9.3、事件广播器
cn.wen.springframework.context.event.ApplicationEventMulticaster
/**
* @ClassName: ApplicationEventMulticaster
* @Author: 小飞
* @Date: 2023/3/28 22:17
* @Description: 用于事件监听器的注册和事件的广播。(管理监听器)
* 监听器的注册就是通过它来实现的,它的作用是把 ApplicationContext 发布的 Event 广播给它的监听器列表。
*/
public interface ApplicationEventMulticaster {
/**
* 监听器注册
* @param listener
*/
void addApplicationListener(ApplicationListener<?> listener);
/**
* 监听器移除
* @param listener
*/
void removeApplicationListener(ApplicationListener<?> listener);
/**
* 广播事件
* @param event
*/
void multicastEvent(ApplicationEvent event);
}
- 在事件广播器中定义了添加监听和删除监听的方法以及一个广播事件的方法 multicastEvent 最终推送时间消息也会经过这个接口方法来处理谁该接收事件。
cn.wen.springframework.context.event.AbstractApplicationEventMulticaster
/**
* @ClassName: AbstractApplicationEventMulticaster
* @Author: 小飞
* @Date: 2023/3/28 22:18
* @Description: 继承 BeanFactoryAware 就是为了获取 BeanFactory 对象
* 实现了 ApplicationEventMulticaster 接口就是管理事件监听的核心类,存储了全部的监听事件对象
* 同时实现了监听事件的添加、移除、获取全部监听事件、判断当前Bean对象是否设置了监听
*/
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanFactoryAware {
public final Set<ApplicationListener<ApplicationEvent>> applicationListeners = new LinkedHashSet<>();
private BeanFactory beanFactory;
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
applicationListeners.add((ApplicationListener<ApplicationEvent>) listener);
}
@Override
public void removeApplicationListener(ApplicationListener<?> listener) {
applicationListeners.remove(listener);
}
@Override
public final void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
protected Collection<ApplicationListener> getApplicationListeners(ApplicationEvent event) {
LinkedList<ApplicationListener> allListeners = new LinkedList<ApplicationListener>();
for (ApplicationListener<ApplicationEvent> listener : applicationListeners) {
if (supportsEvent(listener, event)) allListeners.add(listener);
}
return allListeners;
}
/**
* 监听器是否对该事件感兴趣
*/
protected boolean supportsEvent(ApplicationListener<ApplicationEvent> applicationListener, ApplicationEvent event) {
Class<? extends ApplicationListener> listenerClass = applicationListener.getClass();
// 按照 CglibSubclassingInstantiationStrategy、SimpleInstantiationStrategy 不同的实例化类型,需要判断后获取目标 class
Class<?> targetClass = ClassUtils.isCglibProxyClass(listenerClass) ? listenerClass.getSuperclass() : listenerClass;
Type genericInterface = targetClass.getGenericInterfaces()[0];
Type actualTypeArgument = ((ParameterizedType) genericInterface).getActualTypeArguments()[0];
String className = actualTypeArgument.getTypeName();
Class<?> eventClassName;
try {
eventClassName = Class.forName(className);
} catch (ClassNotFoundException e) {
throw new BeansException("wrong event class name: " + className);
}
// 判定此 eventClassName 对象所表示的类或接口与指定的 event.getClass() 参数所表示的类或接口是否相同,或是否是其超类或超接口。
// isAssignableFrom是用来判断子类和父类的关系的,或者接口的实现类和接口的关系的,默认所有的类的终极父类都是Object。如果A.isAssignableFrom(B)结果是true,证明B可以转换成为A,也就是A可以由B转换而来。
return eventClassName.isAssignableFrom(event.getClass());
}
}
- AbstractApplicationEventMulticaster 是对事件广播器的公用方法提取,这个类也是事件监听器的一些操作实现类。
- 除了像 addApplicationListener、removeApplicationListener,这样的通用方法,这里这个类中主要是对 getApplicationListeners 和 supportsEvent 的处理。
- getApplicationListeners 方法主要是摘取符合广播事件中的监听处理器,具体过滤动作在 supportsEvent 方法中。
- 在 supportsEvent 方法中,主要包括对Cglib、Simple不同实例化需要获取目标Class,Cglib代理类需要获取父类的Class,普通实例化的不需要。接下来就是通过提取接口和对应的 ParameterizedType 和 eventClassName,方便最后确认是否为子类和父类的关系,以此证明此事件归这个符合的类处理。通过判断 Class的关系是否实现了event.getClass 。如果该Class对象表示的类或者接口和指定的 event.getClass() 参数所表示的类或接口相符合说明是设广播事件中的处理器。
1.2.9.4、事件发布者的定义和实现
cn.wen.springframework.context.ApplicationEventPublisher
/**
* @ClassName: ApplicationEventPublisher
* @Author: 小飞
* @Date: 2023/3/28 22:13
* @Description: 事件发布者接口
*/
public interface ApplicationEventPublisher {
/**
* 发布事件方法
* @param event
*/
void publishEvent(ApplicationEvent event);
}
- 事件发布的接口,所有的事件的发布都需要从这个接口中发布出去。
cn.wen.springframework.context.ApplicationContext
/**
* context 是本次实现应用上下文功能新增的服务包
*/
public interface ApplicationContext extends ListableBeanFactory, HierarchicalBeanFactory, ResourceLoader, ApplicationEventPublisher {
}
cn.wen.springframework.context.support.AbstractApplicationContext
/**
* @ClassName: AbstractApplicationContext
* @Author: 小飞
* @Date: 2023/3/27 20:19
* @Description:
*/
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
private ApplicationEventMulticaster applicationEventMulticaster;
/**
* 执行刷新容器功能
* @throws BeansException
*/
@Override
public void refresh() throws BeansException {
// 1、实现创建bean工厂 BeanFactory 然后加载BeanDefinition
refreshBeanFactory();
// 2、获取BeanFactory
// 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
// 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
// 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 3. 添加 ApplicationContextAwareProcessor,让继承自 ApplicationContextAware 的 Bean 对象都能感知所属的 ApplicationContext
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 4、在Bean实例化之前;执行BeanFactoryPostProcessor 方法中的初始化前和初始化后
invokeBeanFactoryPostProcessors(beanFactory);
// 5、BeanPostProcess 需要提前与其他 Bean对象实例化之前进行注册操作
// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
registerBeanPostProcessors(beanFactory);
// 6. 初始化事件发布者
initApplicationEventMulticaster();
// 7. 注册事件监听器
registerListeners();
// 8、提前实例化单例Bean对象
beanFactory.preInstantiateSingletons();
// 9. 发布容器刷新完成事件
finishRefresh();
}
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
Map<String, BeanPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class);
for (BeanPostProcessor beanPostProcessor : beanPostProcessorMap.values()) {
beanFactory.addBeanPostProcessor(beanPostProcessor);
}
}
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
Map<String, BeanFactoryPostProcessor> beanFactoryPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
for (BeanFactoryPostProcessor beanFactoryPostProcessor : beanFactoryPostProcessorMap.values()) {
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
}
}
private void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, applicationEventMulticaster);
}
private void registerListeners() {
Collection<ApplicationListener> applicationListeners = getBeansOfType(ApplicationListener.class).values();
for (ApplicationListener listener : applicationListeners) {
applicationEventMulticaster.addApplicationListener(listener);
}
}
private void finishRefresh() {
publishEvent(new ContextRefreshedEvent(this));
}
@Override
public void publishEvent(ApplicationEvent event) {
applicationEventMulticaster.multicastEvent(event);
}
protected abstract ConfigurableListableBeanFactory getBeanFactory();
protected abstract void refreshBeanFactory();
@Override
public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {
return getBeanFactory().getBeansOfType(type);
}
@Override
public String[] getBeanDefinitionNames() {
return getBeanFactory().getBeanDefinitionNames();
}
@Override
public Object getBean(String name) throws BeansException {
return getBeanFactory().getBean(name);
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
return getBeanFactory().getBean(name, args);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return getBeanFactory().getBean(name, requiredType);
}
@Override
public void registerShutdownHook() {
Runtime.getRuntime().addShutdownHook(new Thread(this::close));
}
@Override
public void close() {
// 发布容器关闭事件
publishEvent(new ContextClosedEvent(this));
// 执行销毁单例bean的销毁方法
getBeanFactory().destroySingletons();
}
}
- 在抽象应用上下文 AbstractApplicationContext#refresh 中,主要新增了 初始化事件发布者、注册事件监听器、发布容器刷新完成事件,三个方法用于处理事件操作。
- 初始化事件发布者中,主要是实例化了一个SimpleApplicationEventMulticaster 事件广播器
- 注册事件监听器,获取 spring.xml 中配置的 Bean 对象。
- 发布容器属性完成事件,发布第一个服务启动后的事件,通过 publishEvent 方法 调用了 applicationEventMulticaster.multicastEvent(event); 方法。
1.2.9.5、测试
cn.wen.springframework.test.event.CustomEvent
public class CustomEvent extends ApplicationContextEvent {
private Long id;
private String message;
public CustomEvent(Object source, Long id, String message) {
super(source);
this.id = id;
this.message = message;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
- 自定义事件
cn.wen.springframework.test.event.CustomEventListener
public class CustomEventListener implements ApplicationListener<CustomEvent> {
@Override
public void onApplicationEvent(CustomEvent event) {
System.out.println("收到:" + event.getSource() + "消息;时间:" + new Date());
System.out.println("消息:" + event.getId() + ":" + event.getMessage());
}
}
- 用于监听 CustomEvent 事件的监听
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean class="cn.wen.springframework.test.event.ContextRefreshedEventListener"/>
<bean class="cn.wen.springframework.test.event.CustomEventListener"/>
<bean class="cn.wen.springframework.test.event.ContextClosedEventListener"/>
</beans>
@Test
public void test_event() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
applicationContext.publishEvent(new CustomEvent(applicationContext, 1019129009086763L, "成功了!"));
applicationContext.registerShutdownHook();
}
2、Spring AOP
2.1、SpringAOP 流程
2.1.1、Aop 自动代理时机
在service bean的创建过程中(也就是getBean(“service”)),AOP通过BeanPostProcess后置处理器操作进行介入 分为2种情况:
- 用户自定义了targetSource,则bean的创建(实例化、填充、初始化)均由用户负责,Spring Ioc不会在管该代理目标对象traget,这种情况基本上不会发生,很多人用了几年Spring可能都不知道有它的存在。
- 正常情况下都是Spring Ioc完成代理对象target的实例化、填充、初始化。然后在初始化后置处理器中进行介入,对bean也就是service进行代理。
2.1.2、源码执行流程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t0cxy9Kv-1690811375720)(https://cdn.nlark.com/yuque/0/2023/png/25484710/1680424860113-f3a7c7e8-3126-48ed-8795-708f64394441.png#averageHue=%23fbfbfa&clientId=ud67858e8-c033-4&from=paste&height=679&id=u7c92e499&originHeight=1019&originWidth=879&originalType=binary&ratio=1.5&rotation=0&showTitle=false&size=86028&status=done&style=none&taskId=u96f277e7-aa7a-447e-9142-2ab2f52e086&title=&width=586)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GxkzeRqO-1690811375720)(https://cdn.nlark.com/yuque/0/2023/png/25484710/1680425023778-17de2606-38d0-45cc-8ad7-16d66f96ee67.png#averageHue=%23fbfbfa&clientId=ud67858e8-c033-4&from=paste&height=309&id=ubffab807&originHeight=464&originWidth=1058&originalType=binary&ratio=1.5&rotation=0&showTitle=false&size=37795&status=done&style=none&taskId=ub90bd4ed-a403-4910-ac02-5035c8d366f&title=&width=705.3333333333334)]
2.1.3、解决循环依赖
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ISdYWMdC-1690811375720)(https://cdn.nlark.com/yuque/0/2023/png/25484710/1680423886636-8d92258e-f7cf-4b1e-a78c-d9822a620053.png#averageHue=%23f6f5f4&clientId=ud67858e8-c033-4&from=paste&height=787&id=u0f773e87&originHeight=1181&originWidth=1793&originalType=binary&ratio=1.5&rotation=0&showTitle=false&size=278744&status=done&style=none&taskId=uc16cef05-4138-40c7-819e-587cd169d7e&title=&width=1195)]
文章末尾有解决循环依赖的详细流程。
2.2、SpringAOP 实现
2.2.1、基于 JDK、Cglib实现AOP切面
如何实现切面编程,我们可以通过代理模式来实现方法的扩展功能,使用AOP可以对业务各部分隔离,从而使各模块之间的业务逻辑耦合度降低,提高代码的可复用性,提高效率。
通过动态代理来动态一个接口的实现类,那么就可以通过代理类来处理需要的逻辑,同时还增强了实现类的功能。如果可以代理掉所有类的方法,就可以做一个方法拦截器,给所有被代理的方法添加上一些自定义处理,比如打印日志、记录耗时、监控异常等。
- 如何给符合规则的方法做代理
- 做完代理后如何把类的职责分离出来。
- 只处理一些需要被拦截的方法。在拦截方法后,执行你对方法的扩展操作。
- 我们就需要先来实现一个可以代理方法的 Proxy,其实代理方法主要是使用到方法拦截器类处理方法的调用 MethodInterceptor#invoke,而不是直接使用 invoke 方法中的入参 Method method 进行 method.invoke(targetObj, args) 这块是整个使用时的差异。
2.2.1.1、工程结构
│
├─src
│ ├─main
│ │ ├─java
│ │ │ └─cn
│ │ │ └─wen
│ │ │ └─springframework
│ │ │ ├─aop
│ │ │ │ │ AdvisedSupport.java #
│ │ │ │ │ ClassFilter.java #
│ │ │ │ │ MethodMatcher.java #
│ │ │ │ │ Pointcut.java #
│ │ │ │ │ TargetSource.java #
│ │ │ │ │
│ │ │ │ ├─aspectj
│ │ │ │ │ AspectJExpressionPointcut.java #
│ │ │ │ │
│ │ │ │ └─framework
│ │ │ │ AopProxy.java #
│ │ │ │ Cglib2AopProxy.java #
│ │ │ │ JdkDynamicAopProxy.java #
│ │ │ │ ReflectiveMethodInvocation.java #
│ │ │ │
│ │ │ ├─beans
│ │ │ │ │ BeansException.java
│ │ │ │ │ PropertyValue.java
│ │ │ │ │ PropertyValues.java
│ │ │ │ │
│ │ │ │ └─factory
│ │ │ │ │ Aware.java
│ │ │ │ │ BeanClassLoaderAware.java
│ │ │ │ │ BeanFactory.java
│ │ │ │ │ BeanFactoryAware.java
│ │ │ │ │ BeanNameAware.java
│ │ │ │ │ ConfigurableListableBeanFactory.java
│ │ │ │ │ DisposableBean.java
│ │ │ │ │ FactoryBean.java
│ │ │ │ │ HierarchicalBeanFactory.java
│ │ │ │ │ InitializingBean.java
│ │ │ │ │ ListableBeanFactory.java
│ │ │ │ │
│ │ │ │ ├─config
│ │ │ │ │ AutowireCapableBeanFactory.java
│ │ │ │ │ BeanDefinition.java
│ │ │ │ │ BeanFactoryPostProcessor.java
│ │ │ │ │ BeanPostProcessor.java
│ │ │ │ │ BeanReference.java
│ │ │ │ │ ConfigurableBeanFactory.java
│ │ │ │ │ SingletonBeanRegistry.java
│ │ │ │ │
│ │ │ │ ├─support
│ │ │ │ │ AbstractAutowireCapableBeanFactory.java
│ │ │ │ │ AbstractBeanDefinitionReader.java
│ │ │ │ │ AbstractBeanFactory.java
│ │ │ │ │ BeanDefinitionReader.java
│ │ │ │ │ BeanDefinitionRegistry.java
│ │ │ │ │ CglibSubclassingInstantiationStrategy.java
│ │ │ │ │ DefaultListableBeanFactory.java
│ │ │ │ │ DefaultSingletonBeanRegistry.java
│ │ │ │ │ DisposableBeanAdapter.java
│ │ │ │ │ FactoryBeanRegistrySupport.java
│ │ │ │ │ InstantiationStrategy.java
│ │ │ │ │ SimpleInstantiationStrategy.java
│ │ │ │ │
│ │ │ │ └─xml
│ │ │ │ XmlBeanDefinitionReader.java
│ │ │ │
│ │ │ ├─context
│ │ │ │ │ ApplicationContext.java
│ │ │ │ │ ApplicationContextAware.java
│ │ │ │ │ ApplicationEvent.java
│ │ │ │ │ ApplicationEventPublisher.java
│ │ │ │ │ ApplicationListener.java
│ │ │ │ │ ConfigurableApplicationContext.java
│ │ │ │ │
│ │ │ │ ├─event
│ │ │ │ │ AbstractApplicationEventMulticaster.java
│ │ │ │ │ ApplicationContextEvent.java
│ │ │ │ │ ApplicationEventMulticaster.java
│ │ │ │ │ ContextClosedEvent.java
│ │ │ │ │ ContextRefreshedEvent.java
│ │ │ │ │ SimpleApplicationEventMulticaster.java
│ │ │ │ │
│ │ │ │ └─support
│ │ │ │ AbstractApplicationContext.java
│ │ │ │ AbstractRefreshableApplicationContext.java
│ │ │ │ AbstractXmlApplicationContext.java
│ │ │ │ ApplicationContextAwareProcessor.java
│ │ │ │ ClassPathXmlApplicationContext.java
│ │ │ │
│ │ │ ├─core
│ │ │ │ └─io
│ │ │ │ ClassPathResource.java
│ │ │ │ DefaultResourceLoader.java
│ │ │ │ FileSystemResource.java
│ │ │ │ Resource.java
│ │ │ │ ResourceLoader.java
│ │ │ │ UrlResource.java
│ │ │ │
│ │ │ └─util
│ │ │ ClassUtils.java
│ │
│ └─test
│ ├─java
│ │ └─cn
│ │ └─wen
│ │ └─springframework
│ │ └─test
│ │ │ ApiTest.java
│ │ │
│ │ ├─bean
│ │ │ IUserService.java
│ │ │ UserService.java
│ │ │ UserServiceInterceptor.java
│ │
│ └─resources
│ spring.xml
- 整个类关系图就是 AOP 实现核心逻辑的地方,上面部分是关于方法的匹配实现,下面从 AopProxy 开始是关于方法的代理操作。
- Pointcut:切入点接口,提供不同粒度的拦截器匹配器。
- ClassFilter:定义类匹配类,用于切点找到给定的接口和目标类。Class级别的限定Joinpoin的匹配范围,粒度更大
- MethodMatcher:定义方法匹配器,粒度属于方法层。
- AspectJExpressionPointcut:AspectJExpressionPointcut 的核心功能主要依赖于 aspectj 组件并处理 Pointcut、ClassFilter,、MethodMatcher 接口实现,专门用于处理类和方法的匹配过滤操作。
- TargetSource:封装目标对象的类,将被代理的类进行封装,提供被代理对象的一些方法,包括:getTargetClass、getTarget等方法。
- ReflectMethodInvocation:封装代理对象性、代理方法、拦截器链等信息类,同时还有MethodInvocation功能,间接实现了Invocation和JoinPoint。
- AopProxy:AopProxy 是代理的抽象对象,它的实现主要是基于 JDK 的代理和 Cglib 代理。
- AdvisedSupport:提供织入需要的信息,将代理、拦截、匹配的各项属性封装到该类,同时封装了Advice 和 Advisor操作。
- Cglib2AopProxy:Cglib2的动态代理实现类
- JDKDynamicAopProxy:JDK 的动态代理实现类
2.2.1.2、代码案例
@Test
public void test_proxy_method() {
// 目标对象(可以替换成任何的目标对象)
Object targetObj = new UserService();
// AOP 代理
IUserService proxy = (IUserService) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), targetObj.getClass().getInterfaces(), new InvocationHandler() {
// 方法匹配器
MethodMatcher methodMatcher = new AspectJExpressionPointcut("execution(* cn.wen.springframework.test.bean.IUserService.*(..))");
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (methodMatcher.matches(method, targetObj.getClass())) {
// 方法拦截器
MethodInterceptor methodInterceptor = invocation -> {
long start = System.currentTimeMillis();
try {
return invocation.proceed();
} finally {
System.out.println("监控 - Begin By AOP");
System.out.println("方法名称:" + invocation.getMethod().getName());
System.out.println("方法耗时:" + (System.currentTimeMillis() - start) + "ms");
System.out.println("监控 - End\r\n");
}
};
// 反射调用
return methodInterceptor.invoke(new ReflectiveMethodInvocation(targetObj, method, args));
}
return method.invoke(targetObj, args);
}
});
String result = proxy.queryUserInfo();
System.out.println("测试结果:" + result);
}
2.2.1.3、切点表达式
:::info
定义接口
:::
cn.wen.springframework.aop.Pointcut
/**
* @ClassName: Pointcut
* @Author: 小飞
* @Date: 2023/3/29 16:11
* @Description: 切入点接口,定义用于获取 ClassFilter、MethodMatcher 的两个类,
* 这两个接口获取都是切点表达式提供的内容
*/
public interface Pointcut {
/**
* 获取反射类拦截器(匹配器)
* @return
*/
ClassFilter getClassFilter();
/**
* 获取方法匹配器
* @return
*/
MethodMatcher getMethodMatcher();
}
- 切入点接口,定义用于获取 ClassFilter、MethodMatcher 的两个类,这两个接口获取都是切点表达式提供的内容。
cn.wen.springframework.aop.ClassFilter
/**
* @ClassName: ClassFilter
* @Author: 小飞
* @Date: 2023/3/29 16:17
* @Description: 定义类匹配类,用于切点找到给定的接口和目标类。Class级别的限定Joinpoin的匹配范围,粒度更大
*/
public interface ClassFilter {
/**
* 反射类匹配器 true表示能够匹配。那就会进行织入的操作
* @param clazz
* @return
*/
boolean matches(Class<?> clazz);
}
- 定义类匹配类,用于切点找到给定的接口和目标类。
cn.wen.springframework.aop.MethodMatcher
/**
* @ClassName: MethodMatcher
* @Author: 小飞
* @Date: 2023/3/29 16:18
* @Description: 方法匹配接口
*/
public interface MethodMatcher {
/**
* 通过方法对象和反射类匹配器
* 这个称为静态匹配:在匹配条件不是太严格时使用,可以满足大部分场景的使用
* @param method
* @param targetClass
* @return
*/
boolean matches(Method method, Class<?> targetClass);
}
- 方法匹配,找到表达式范围内匹配下的目标类和方法。在上文的案例中有所体现:methodMatcher.matches(method, targetObj.getClass())
:::info
实现切点表达式类
:::
cn.wen.springframework.aop.aspectj.AspectJExpressionPointcut
/**
* @ClassName: AspectJExpressionPointcut
* @Author: 小飞
* @Date: 2023/3/29 16:53
* @Description: 切点表达式 解析和匹配切点表达式的方法,其中包括切点表达式的解析规则
* 它和Expression有关,而这个切点表达式,最终还是依赖于AspectJ的jar包去解析的 @Aspect大量使用
* 可以精确到返回参数,参数类型,方法名,当然,也可以模糊匹配
*/
public class AspectJExpressionPointcut implements Pointcut, ClassFilter, MethodMatcher {
private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet<PointcutPrimitive>();
// 下面是AspectJ的切点语言支持注册
static {
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
}
// PointcutExpression是org.aspectj.weaver.tools.PointcutExpression是AspectJ的类
private final PointcutExpression pointcutExpression;
/**
* 初始化一个Pointcut的解析器。
*/
public AspectJExpressionPointcut(String expression) {
PointcutParser pointcutParser = PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(SUPPORTED_PRIMITIVES, this.getClass().getClassLoader());
pointcutExpression = pointcutParser.parsePointcutExpression(expression);
}
@Override
public boolean matches(Class<?> clazz) {
return pointcutExpression.couldMatchJoinPointsInType(clazz);
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
return pointcutExpression.matchesMethodExecution(method).alwaysMatches();
}
@Override
public ClassFilter getClassFilter() {
return this;
}
@Override
public MethodMatcher getMethodMatcher() {
return this;
}
}
- 切点表达式实现了 Pointcut、ClassFilter、MethodMatcher,三个接口定义方法,同时这个类主要是对 aspectj 包提供的表达式校验方法使用。
2.2.1.4、包装切面通知信息
cn.wen.springframework.aop.TargetSource
/**
* @ClassName: TargetSource
* @Author: 小飞
* @Date: 2023/3/29 16:20
* @Description: 被代理的目标对象,获取 AOP 调用的当前目标
* 在调用 AOP 代理对象的方法时,在执行完所有的 advice chain 之后,最终会通过反射调用这个目标 target 的方法。
*/
public class TargetSource {
// 被代理的对象
private final Object target;
public TargetSource(Object target) {
this.target = target;
}
/**
* 获取目标对象的接口列表
* @return
*/
public Class<?>[] getTargetClass(){
return this.target.getClass().getInterfaces();
}
/**
* 获取目标对象
* @return
*/
public Object getTarget(){
return this.target;
}
}
- 提供目标对象的 信息的方法。
cn.wen.springframework.aop.AdvisedSupport
/**
* @ClassName: AdvisedSupport
* @Author: 小飞
* @Date: 2023/3/29 16:34
* @Description: 要是用于把代理、拦截、匹配的各项属性包装到一个类中,方便在 Proxy 实现类进行使用。
* AOP代理配置管理器的基类。 它封装了AOP中对通知 (Advice)和通知器 (Advisor)的相关操作,
* 这些操作对于不同的AOP的代理对象的生成都是一样的,但对于具体的AOP代理对象的创建,AdvisedSupport把它交给子类去实现。
*/
public class AdvisedSupport {
// 被代理的目标对象
private TargetSource targetSource;
// 方法拦截器
private MethodInterceptor methodInterceptor;
// 方法匹配器(检查目标方法是否符合通知条件)
private MethodMatcher methodMatcher;
public TargetSource getTargetSource() {
return targetSource;
}
public void setTargetSource(TargetSource targetSource) {
this.targetSource = targetSource;
}
public MethodInterceptor getMethodInterceptor() {
return methodInterceptor;
}
public void setMethodInterceptor(MethodInterceptor methodInterceptor) {
this.methodInterceptor = methodInterceptor;
}
public MethodMatcher getMethodMatcher() {
return methodMatcher;
}
public void setMethodMatcher(MethodMatcher methodMatcher) {
this.methodMatcher = methodMatcher;
}
}
- AdvisedSupport,主要是用于把代理、拦截、匹配的各项属性包装到一个类中,方便在 Proxy 实现类进行使用。这和你的业务开发中包装入参是一个道理
- TargetSource,是一个目标对象,在目标对象类中提供 Object 入参属性,以及获取目标类 TargetClass 信息。
- MethodInterceptor,是一个具体拦截方法实现类,由用户自己实现 MethodInterceptor#invoke 方法,做具体的处理。
2.2.1.5、代理抽象实现类(JDK&Cglib)
:::info
定义接口
:::
cn.wen.springframework.aop.framework.AopProxy
/**
* @ClassName: AopProxy
* @Author: 小飞
* @Date: 2023/3/29 16:25
* @Description: AOP 代理的抽象
*/
public interface AopProxy {
// 获取代理类
Object getProxy();
}
- 定义一个标准接口,用于获取代理类。定义接口,不同的实现类可以更加方便管理,策略模式。
cn.wen.springframework.aop.framework.Cglib2AopProxy
/**
* @ClassName: Cglib2AopProxy
* @Author: 小飞
* @Date: 2023/3/29 16:26
* @Description:
*/
public class Cglib2AopProxy implements AopProxy {
private final AdvisedSupport advised;
public Cglib2AopProxy(AdvisedSupport advised) {
this.advised = advised;
}
@Override
public Object getProxy() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(advised.getTargetSource().getTarget().getClass());
enhancer.setInterfaces(advised.getTargetSource().getTargetClass());
enhancer.setCallback(new DynamicAdvisedInterceptor(advised));
return enhancer.create();
}
/**
* 内部静态类
* 作用:首先setCallback方法是实现AOP增强逻辑的作用,那么DynamicAdvisedInterceptor的类
* 实现了MethodInterceptor接口就是增强方法拦截器,实现 intercept 方法来增强处理AOP逻辑。
* 当目标是动态的或代理未被冻结时使用 , 会使用该通用的AOP回调
*/
private static class DynamicAdvisedInterceptor implements MethodInterceptor {
// 包含AOP配置
private final AdvisedSupport advised;
public DynamicAdvisedInterceptor(AdvisedSupport advised) {
this.advised = advised;
}
/**
* @param o EnhancerBySpringCGLIB 代理
* @param method 实际业务方法
* @param objects 方法参数
* @param methodProxy
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
CglibMethodInvocation methodInvocation = new CglibMethodInvocation(advised.getTargetSource().getTarget(), method, objects, methodProxy);
// 通过方法匹配器来判断是否拦截成功
if (advised.getMethodMatcher().matches(method, advised.getTargetSource().getTarget().getClass())) {
return advised.getMethodInterceptor().invoke(methodInvocation);
}
return methodInvocation.proceed();
}
}
/**
* 继承了 ReflectiveMethodInvocation 类,获取父类的target、method、args等父类属性,
* 通过传入的方法代理对象来执行目标类的目标方法,同时传入参数
* 该类中定义了拦截器链以及拦截器链的执行逻辑
*/
private static class CglibMethodInvocation extends ReflectiveMethodInvocation {
private final MethodProxy methodProxy;
public CglibMethodInvocation(Object target, Method method, Object[] arguments, MethodProxy methodProxy) {
super(target, method, arguments);
this.methodProxy = methodProxy;
}
/**
* 代理类的执行目标类的目标方法
* @return
* @throws Throwable
*/
@Override
public Object proceed() throws Throwable {
return this.methodProxy.invoke(this.target, this.arguments);
}
}
}
- 基于 Cglib 使用Enhancer代理的类可以在运行期间为接口使用ASM字节码增强处理对象生成。
- 扩展进去的用户拦截方法使用Enhancer#setCallback 中处理,用户自己的新增的拦截处理。
cn.wen.springframework.aop.framework.JdkDynamicAopProxy
/**
* @ClassName: JdkDynamicAopProxy
* @Author: 小飞
* @Date: 2023/3/29 16:51
* @Description: JDK 动态代理 JDK动态代理逻辑比较简单,获取到目标类、目标方法、参数直接执行invoke方法。
*/
public class JdkDynamicAopProxy implements AopProxy, InvocationHandler {
private final AdvisedSupport advised;
public JdkDynamicAopProxy(AdvisedSupport advised) {
this.advised = advised;
}
@Override
public Object getProxy() {
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), advised.getTargetSource().getTargetClass(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (advised.getMethodMatcher().matches(method, advised.getTargetSource().getTarget().getClass())) {
MethodInterceptor methodInterceptor = advised.getMethodInterceptor();
return methodInterceptor.invoke(new ReflectiveMethodInvocation(advised.getTargetSource().getTarget(), method, args));
}
return method.invoke(advised.getTargetSource().getTarget(), args);
}
}
- 基于 JDK 实现的代理类,实现 AopProxy、InvocationHandler 就可以将代理对象 getProxy 和反射调用方法 invoke 隔离处理。
- invoke 方法中主要处理匹配的方法后,使用用户自己提供的方法拦截实现,做反射调用 methodInterceptor.invoke 。
- ReflectiveMethodInvocation,其他它就是一个入参的包装信息,提供了入参对象:目标对象、方法、入参。
cn.wen.springframework.aop.framework.ReflectiveMethodInvocation
/**
* @ClassName: ReflectiveMethodInvocation
* @Author: 小飞
* @Date: 2023/3/29 16:27
* @Description: ReflectiveMethodInvocation实现了aop联盟的MethodInvocation,间接实现了Invocation和JoinPoint。
* 将代理对象、目标方法、拦截器链等信息封装到该类中
*/
public class ReflectiveMethodInvocation implements MethodInvocation {
// 目标对象
protected final Object target;
// 目标方法
protected final Method method;
// 入参
protected final Object[] arguments;
public ReflectiveMethodInvocation(Object target, Method method, Object[] arguments) {
this.target = target;
this.method = method;
this.arguments = arguments;
}
@Override
public Method getMethod() {
return method;
}
@Override
public Object[] getArguments() {
return arguments;
}
/**
* 核心方法
* @return
* @throws Throwable
*/
@Override
public Object proceed() throws Throwable {
return method.invoke(target, arguments);
}
/**
* 获取当前目标对象
* @return
*/
@Override
public Object getThis() {
return target;
}
@Override
public AccessibleObject getStaticPart() {
return method;
}
}