4.7.1 Spring
4.7.1.1 Spring模块
Spring 由七大模块组成,分别是
- 数据模块(Data Access / Integration)
- Web模块
- 切面模块(Aop,Aspects)
- 工具模块(Instrumentation)
- 消息模块
- 核心模块
- 测试模块
4.7.1.1.1 数据模块
数据访问与集成模块,分为以下小模块:
JDBC
(Java Database Connectivity),Java数据库连接ORM
(Object Relational Mapping), 对象关系映射OXM
(Object XML Mapping), 对象XML映射JMS
(Java Message Service),Java消息服务Transactions
,事务
4.7.1.1.2 Web模块
Web有以下小模块:
- Web
- WebMVC
- WebSocket
- WebFlux
Web 模块:提供了核心部分,如 编解码,过滤器,序列化,国际化,跨域,转换器,客户端和服务端等。
WebMVC 模块:即我们平时用的 SpringMVC
WebSocket 模块: 用来支持这个 全双工通信
WebFlux模块: 就是这个响应式Web编程模块
4.7.1.1.3 切面模块
包括AOP、Aspect两个模块。
AOP:基于代理的 Aop 框架
Aspect:定义了五种类型的切面
- beans.factory.aspectj
- cache.aspectj
- context.annotation.aspectj
- scheduling.aspectj
- transaction.aspectj
4.7.1.1.4 工具模块
Instrumentation , 这个是 Java 的一个接口,用于
- 监控代理
- 事件日志记录
- 代码覆盖率
4.7.1.1.5 消息模块
Spring-messaging
模块提供了一种基于 WebSocket
的 STOMP
协议实现STOMP
(Simple Text Oriented Messaging Protocol) 是一种 流文本定向消息协议,也是一种为MOM(Message Oriented Middleware,面向消息的中间件)设计的简单文本协议
常见的这几个MQ都支持该协议,比如 RocketMQ
,RabbitMQ
,ActiveMQ。
待更新
Spring的这七大模块你了解吗? - 知乎
4.7.1.1.6 核心模块
分为四个核心模块:
- Beans
- Core
- Context
- Expression
该核心模块为重点,
4.7.1.1.7 测试模块
主要是测试用,如Junit等。
4.7.1.2 核心模块
4.7.2 SpringIOC架构原理
4.7.2.1 Bean初始化状态
我们可以将bean概念态、定义态、纯静态、成熟态
概念态:
定义态:bean的构造图
纯静态:循环依赖中体现纯静态的作用
成熟态:最终在应用中使用的bean
其中在ApplicationContext()中隐藏了另外两种状态
4.7.2.2 概念bean → 定义bean
BeanDefinition是相当重要的
BeanDefinition:封装了bean的定义信息,决定一个bean是怎么生产的,一个bean对应一个BeanDefinition
那么这个BeanDefinition是怎么来的呢?
当我们new ApplicationContext时会传入一个xml文件。不同的sapring上下文会传入不同的,读取bean定义的过程是有些不同的,但也有相同的地方。
方式一:ClassPathXmlApplicationContext(xml);
方式二:AnnotationConfigApplicationContext(配置类);
无论是ClassPathXmlApplicationContext(xml)还是AnnotationConfigApplicationContext(配置类)都有一个统一的接口ApplicationContext,因此它们会将公共的部分抽取出来,我们来研究这些公共的部分。
虽然有不同的spring上下文,但是都是由BeanDefinitionReader接口读取配置信息
读取之后怎么解析注解呢?
用扫描器ClassPathBeanDefinitionScanner,比如,我们定义了
它会扫描包下的.class,里面有component注解,将这个类注册为BeanDefinition。由于每个类都会有BenaDefinition,所以用beanDefinitionMap容器保存。
之后由registerBeanDefinition将BeanDefinition注册到BeanDefinitionMap中
之后就是生产bean了。
4.7.2.3 生产bean
这里涉及到很重要的知识点:BeanFactory接口
BeanFactory负责生产,在BeanFactory中提供了getBean方法用来生产bean。
提出一个小问题,这里Spring容器调用的getBean和BeanFactory里的getBean是同一个方法吗?
答案:是同一个
我们进入applicationContext.getBean(),会发现这里的getBean是门面方法,没有具体,而是交给BeanFactory去生产。
当已存在bean就直接返回给spring,如果没有就生产后返回。
既然ApplicationContext和BeanFactory都可以获取bean,也就是说二者均可作为容器去使用。
那么既然都可以作为容器,为什么不直接在spring中书写BeanFactroy,非要再整个ApplicationContext的门面方法,不多此一举么?
看完上面的继承图,我们发现ApplicationContext实现了BeanFactroy,这就好比,我们要买车,我们可以选择去4S店,也可以选择直接去汽车工厂。ApplicationContext就好比4S店,4S店有很多的服务,我们只需要提需求,4S店都能完成。BeanFactroy就是汽车工厂,工厂的职责就一个:生产汽车。基本上我们和4S店比较熟悉,打交道比较多,同样我们开发人员和ApplicationContext打交道比较多。我们只需要把配置给ApplicationContext,它就能初始化。
但是BeanFactroy不行,它只实现了简单工厂,功能单一化,只能根据BeanDefinition去生产bean。
通过ApplicationContext,我们只需要getBean(car),就可以得到我们想要的bean,但是,如果注释了ApplicationContext,我们再直接用beanFactory.get(car),就会报错BeanDefinitionException。
因为像xml、配置类的信息,都是由ApplicationContext(Spring 上下文)帮我们做了,ApplicationContext调用了BeanFactory来生产bean。
但是对于BeanFactory,我们必须手动将BenaDefinition传给BeanFactory,才能生产bean。
但是BeanFactory内存更小,可以用于嵌入式开发。
4.7.2.4 实例化bean
实例化bean的方式:
- 反射
- 工厂方法
- 工厂类:FactoryBean
4.7.2.4.1 反射
@Component
将类读取到beanClass中,spring利用反射实例化bean
4.7.2.4.2 工厂方法
注解形式
public class StaticFactoryBean {
@Bean
public static UserService createUserService(){
return new UserServiceImpl();
}
}
会将被标注的方法读取到factoryMethodName
xml形式
而<bean id="" factory-bean="StaticFactoryBean全限定名" factory-method=" UserService"/>
在factory-method=" "中指定一个工厂方法,且这个工厂方法是静态的,会将方法读取到factoryMethodName
4.7.2.4.3 工厂类
注意FactoryBean本身也是一个bean
类实例化FactoryBean接口,并重写getObject()、getObjectType()
@Component
public class FactoryBean_test implements FactoryBean {
@Override
public Object getObject() throws Exception {
//这个才是返回的真正的bean
return new User();
}
@Override
public Class<?> getObjectType() {
return User.class;
}
工厂方法基于方法,而工厂类基于类
4.7.2.5 属性注入
4.7.2.5.1 循环依赖
4.7.2.6 初始化
4.7.2.6.1 初始化方法
属性注入之后,进行初始化,初始化时会调用init_Method()
除了init-Method()外
还可以用注解@PostConstruct声明一个初始化方法
以及利用InitializingBean接口,实现一个InitializingBean,重写afterPropertiesSet()
4.7.2.6.2 aware扩展接口
检查aware接口设置相关依赖
在spring容器中,我们可以把对象按照使用者分为两类:自定义对象、容器使用的对象
- 自定义对象:就是我们开发人员定义的Student、Taecher等对象
- 容器使用的对象:BeanPostProcessor、BeanFactory等,这些都是由容器自己创建、自己调用。
但是如果我们自定义对象需要使用、调用这些容器所使用的对象时,怎么办?
你可以把这些容器所使用的对象当成一个普通属性,如果是属性,我肯定要调用属性的set方法,往里面赋值。但是,对象的创建都交由容器来管理了,set方法调用肯定还是由容器管理,而且容器又不知道什么时候调用。
所以这里设置了统一的入口——aware接口。
所有调用容器对象设置的地方都会实现aware接口,如BeanFactoryAware、BeanNameAware等。
总的来说就是通过aware的具体实现子类,我们可以设置bean的一系列操作。
4.7.2.7 创建Bean
创建好的bean会放入Map(单例池/一级缓存)中
当context.getBean("bean的名字");时,会到一级缓存中查询,有就返回,没有就生产。
4.7.2.8 扩展接口
4.7.2.8.1 BeanFactoryPostProcessor接口
@FunctionalInterface
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory BeanFactory) throws BeansException;
}
BeanFactoryPostProcessor中的postProcessBeanFactory()方法,直接传来一个
4.7.2.8.2 BeanDefinitionRegistryPostProcessor
源码定义如下:
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}
BeanDefinitionRegistryPostProcessor的作用是注册BeanDefinition,也就是注册了Bean
Spring-MyBatis中的Mapper是接口,动态代理
4.7.2.8.3 BeanPostProcessor
BeanPostProcessor(bean的后置处理器)主要用在初始化前后
BeanPostProcessor有很多子接口
4.7.3 Bean生命周期
4.7.3.1 简化版本
1、实例化bean,当客户向容器请求一个尚未初始化的bean时,容器就会调用doCreateBean()方法进行实例化,实际上就是利用反射来创建一个bean对象
2、当bean对象创建出来后就对bean对象进行属性填充,也就是注入这个bean依赖的其他对象
3、属性填充完成后,进行初始化bean操作
a、执行Aware接口方法,Spring会检查该bean对象是否实现了xxxAware接口,通过Aware类型的接口,我们可以拿到spring容器的一些资源,如实现了BeanNameAware接口就可以获取BeanName等等
b、执行BeanPostProcessor的前置处理方法postProcessBeforeInitialization(),对Bean进行一些自定义的前置处理
c、判断bean是否实现了InitialalizationBean接口,如果实现了,将会执行InitialalizationBean的afterPropertiesSet()初始化方法
d、执行用户自定义的初始化方法,如init-method等
e、执行BeanPostProcessor的后置处理方法postProcessAfterInitialization()
4、销毁
a、首先判断Bean是否实现了DestructionAwareBeanPostProcessor接口,如果实现了,则执行DestructionAwareBeanPostProcessor后置处理器的销毁方法
b、其次判断Bean是否实现了DisposableBean接口,如果实现了就会调用其实现的destroy()方法
c、最后判断Bean是否配置了destroy-method方法,如果有就调用其配置的销毁方法
4.7.3.2 详细版本
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
//bean
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
//如果缓存中不存在,则调用createBeanInstance创建一个BeanWrapper(bean的包装类)
if (instanceWrapper == null) {
//bean的实例化
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
//初始化bean实例
Object exposedObject = bean;
//----------------省略-----------
//属性填充
this.populateBean(beanName, mbd, instanceWrapper);
//初始化bean,如执行aware接口的子类,执行init-method方法,BeanPostProcesso后置增强等
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
//销毁不在AbstractAutowireCapableBeanFactory 类,在DisposableBeanAdapter类中
}
initializeBean
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(() -> {
//先执行aware的子类
this.invokeAwareMethods(beanName, bean);
return null;
}, this.getAccessControlContext());
} else {
this.invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//执行beanPostProcessor后置处理器的前置方法BeanPostProcessorsBeforeInitialization
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
//中间执行init-method
try {
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
}
//最后执行BeanPostProcessorsAfterInitialization
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
invokeAwareMethods
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
//如果bean实现了BeanNameAware,那bean内部可以获取到beanName属性
if (bean instanceof BeanNameAware) {
((BeanNameAware)bean).setBeanName(beanName);
}
//其他同理
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = this.getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware)bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware)bean).setBeanFactory(this);
}
}
}
invokeInitMethods
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
//InitialalizationBean接口,如果实现了,将会执行InitialalizationBean的afterPropertiesSet()初始化方法
boolean isInitializingBean = bean instanceof InitializingBean;
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
//执行afterPropertiesSet()
AccessController.doPrivileged(() -> {
((InitializingBean)bean).afterPropertiesSet();
return null;
}, this.getAccessControlContext());
} catch (PrivilegedActionException var6) {
throw var6.getException();
}
} else {
((InitializingBean)bean).afterPropertiesSet();
}
}
//用户自定义的初始化方法
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) && (!isInitializingBean || !"afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) {
//用户自定义的方法
this.invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
DisposableBeanAdapter
//销毁
class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
public void destroy() {
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
Iterator var1 = this.beanPostProcessors.iterator();
while(var1.hasNext()) {
//先查看DestructionAwareBeanPostProcessor接口
DestructionAwareBeanPostProcessor processor = (DestructionAwareBeanPostProcessor)var1.next();
//如果实现了,则执行DestructionAwareBeanPostProcessor后置处理器的销毁方法
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
//接着看是否实现了DisposableBean接口
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(() -> {
//如果实现了就调用接口的destroy方法
((DisposableBean)this.bean).destroy();
}
}
//最后判断是否有用户自定义的销毁方法
if (this.destroyMethod != null) {
this.invokeCustomDestroyMethod(this.destroyMethod);
} else if (this.destroyMethodName != null) {
Method methodToInvoke = this.determineDestroyMethod(this.destroyMethodName);
if (methodToInvoke != null) {
//调用用户自定义的销毁方法
this.invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
}
}
}
Spring的理解
Spring是什么?
框架:方便开发,整合其他框架
容器:管理bean
生态:目前主流的Java开发,都会用到Java全家桶。Springboot、Springcloud等框架都是对Spring的扩展实现。
11张流程图搞定 Spring Bean 生命周期 - 知乎
4.7.3.3 循环依赖
4.7.3.3.1 循环依赖问题
4.7.3.3.2 解决方案:三级缓存
singletonObject(一级缓存):存放实例化 -> 代理 -> 属性注入 ->初始化后的对象
earlySingletonObjects(二级缓存):存放实例化 -> 代理 -> 属性注入 ->初始化后的对象
singletonFactories(三级缓存):存放对象工厂,可以从对象工厂中拿到还未属性注入的对象(对象工厂便于创建代理对象)
4.7.3.3.3 流程
当getBean(),获取bean时,spring会先到一级缓存中找,没有再去二级缓存,若二级缓存还没有就会创建一个对应的工厂对象
4.7.4 AOP
单例bean
Spring中的Bean对象默认是单例的,框架并没有对Bean进行多线程封装处理
单例bean是指IOC容器中就只有这么一个bean,是全局共享的。分为有状态bean和无状态bean。
有状态的bean
就是有实例变量的对象,可以保存数据(有状态就是有数据存储功能),是线程不安全的。每个用户都有自己特有的实例,在用户的生命周期中,bean保存了用户的信息,即为“偶状态”;一旦用户衰亡(调用结束),bean的生命周期也随之结束。即每个用户最初都会得到一个初始的bean。
无状态的bean
就是没有实例变量的对象,不能保存数据,是不变类,是线程安全的。bean一旦实例化就被加进会话池中,各个用户都可以共用。即使用户已经消亡,bean的生命期也不一定结束,它可能依然存在于会话池中,供其他用户调用。由于没有特定的用户,那么也就不能保持某一用户的状态,所以叫无状态bean。但无状态会话bean 并非没有状态,如果它有自己的属性(变量),那么这些变量就会受到所有调用它的用户的影响,这是在实际应用中必须注意的。
实例变量
java类的成员变量有俩种:一种是被static关键字修饰的变量,叫类变量或者静态变量;另一种没有static修饰,为实例变量。
如
class Car{
private name; //这就是实例变量
public void 方法(){};
}
当一个对象被实例化之后,每个实例变量的值就跟着确定;
实例变量在对象创建的时候创建,在对象被销毁的时候销毁;
如果Bean是有状态的,那就需要开发人员自己来进行线程安全的保证,最简单的办法就是改变bean的作用域 把 "singleton"改为’‘protopyte’ 这样每次请求Bean就相当于是 new Bean() 这样就可以保证线程的安全了。
无状态就是不会存储数据,试想controller,service和dao本身并不是线程安全的,只是调用里面的方法,而且多线程调用一个实例的方法,会在内存中复制遍历,这是自己线程的工作内存,是最安全的。因此在进行使用的时候,不要在bean中声明任何有状态的实例变量或者类变量,如果必须如此,也推荐大家使用ThreadLocal把变量变成线程私有,如果bean的实例变量或者类变量需要在多个线程之间共享,那么就只能使用synchronized、lock、cas等这些实现线程同步的方法。但是一旦使用了synchronized、lock等线程同步方法,又会降低系统效率。