文章目录
1. Spring IOC & AOP
IOC:(Inverse of Control:控制反转)是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理。IoC容器是Spring用来实现IoC的载体,IoC容器实际上就是个Map(key,value),Map中存放的是各种对象。
将对象之间的相互依赖关系交给IoC容器来管理,并由IoC容器完成出来对象的注入。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。IoC容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。
AOP:能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务管理、日志管理、权限控制)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
Spring AOP是基于动态代理的,如果要代理的对象,实现了某个接口,那么Spring AOP会使用JDK Proxy,去创建代理对象,而对于没有实现接口的对象(有些类单类,不去实现接口),就无法使用JDK Proxy去进行代理,这时候Spring AOP会使用Cglib,生成一个被代理对象的子类来作为代理。
1.1 源码阅读
以下通过一些简洁的语言简述了IOC容器创建的过程以及bean的生命周期。
/**
* IOC 容器刷新过程
* @throws BeansException
* @throws IllegalStateException
*/
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
/**
* 第一步:
* 1. 初始化一些属性。
* 2. 校验属性的合法性
* 3. 保存容器刷新的一些早期事件。
*/
prepareRefresh();
/**
* 第二步:
* 1.创建 beanFactory (通过 CAS 设置创建的属性,CAS 真是无处不在)
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
/**
* 第三步:
* 1. 给 beanFactory 添加一些属性和组件
*/
prepareBeanFactory(beanFactory);
try {
/**
* 第四步:
* 1. 空方法,子类实现该方法进行自定义逻辑
*/
postProcessBeanFactory(beanFactory);
/**
* 第五步:
* 1. 执行 beanFactory 的后置处理器。主要包括 BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor
*/
invokeBeanFactoryPostProcessors(beanFactory);
/**
* 第六步:
* 1. 注册所有的 BeanPostProcessors 到 beanFactory
*/
registerBeanPostProcessors(beanFactory);
/**
* 第七步:
* 1. 初始化 MessageSource 组件,主要用于国际化,消息绑定解析等
*/
initMessageSource();
/**
* 第八步:
* 1. 初始化 ApplicationEventMulticaster 事件多播器,用于事件的广播
*/
initApplicationEventMulticaster();
/**
* 第九步:
* 1. 空方法,子类可以实现该方法自定义逻辑
* 2. 例如 SpringMVC 在该方法初识了八大组件,Tomcat 在该方法创建启动。
*/
onRefresh();
/**
* 第十步:
* 1. 注册 Listeners 监听器,监听之间多播器的内容
*/
registerListeners();
/**
* 第十一步:( bean 的生命周期)
* 1. 通过 getBean() 获取类的 BeanDefinition 定义信息。
* 2. BeanDefinition 定义信息中存储了对象的各种属性。
* 3. 通过 createBean() 方法真正创建对象。
* 4. 先调用 Instantiation 前后的 BeanPostProcessor 后置处理器
* 5. 如果有实现各种 xxxAware 接口的则设置一些值。
* 6. 然后执行初始化方法,初始化前后又有 Initialization 的后置处理器
* (1) AOP 功能就在此处实现:
* (2)通过 AnnotationAwareAspectJAutoProxyCreator 会调用 postProcessAfterInitialization() 方法
* (3)该后置处理器会检查生成的对象是否是需要增强的对象
* (4)如果是,则保存它的所有增强方法,并创建一个代理对象返回
* (5)之后对该对象的获取,其实是获取了它的代理对象
* (6)执行方法时会被拦截器,将该代理对象的所有增强方法包装成一个拦截器链,进行链式调用
* 7. 最后给该对象注册销毁方法
* 8. 穿件完成之后,将单例对象加入到单例池中
*/
finishBeanFactoryInitialization(beanFactory);
/**
* 第十二步:
* 1. 完成刷新,清理一些内容。
*/
finishRefresh();
}
/**
* 如果捕捉到异常就销毁所有 bean 并取消刷新标记。
*/
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
destroyBeans();
cancelRefresh(ex);
throw ex;
}
finally {
resetCommonCaches();
}
}
}
1.2 解决单例的循环依赖
循环依赖通过三级缓存解决:
- 第一级:
singletonObjects
:用于存放完全初始化好的bean,从该缓存中取出的bean可以直接使用。 - 第二级:
earlySingletonObjects
:存放原始的bean对象(尚未填充属性),用于解决循环依赖 - 第三级:
singletonFactories
:存放bean工厂对象,用于解决循环依赖
例如 :
- A 的属性依赖于 B,B 又依赖于 A,所以当 A 创建对象的时候,先进行了第一步操作,获取到了工厂bean,并加入到第三级缓存中,继续初始化的时候发现需要注入 B,则先去创建B。
- B 发现自己需要注入 A,则先去获取 A,发现,第一级缓存和第二级缓存都没有,但是可以从第三级缓存中获取,则获取到A,并完成了创建。
- 之后 A 也可以获取到 B 完成创建。
2. Spring 事务
2.1 事务传播
事务就是 AOP 的具体应用,会生成开启事务方法的代理对象,在获取该对象操作时,会执行代理对象的方法,先设置事务为非自动提交,然后开启事务,最后提交事务或者回滚事务。
事务的传播级别:
/**
* 如果当前存在事务,则加入该事务,不存在则创建一个新的事务
*/
REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),
/**
* 如果当前存在事务,加入该事务,不存在则以非事务的方式运行
*/
SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),
/**
* 如果当前存在事务,加入该事务,不存在则抛出异常
*/
MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),
/**
* 创建一个新的事务,如果当前存在事务则挂起
*/
REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
/**
* 非事务方式运行,有事务则挂起
*/
NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
/**
* 非事务方式运行,存在事务则抛出异常
*/
NEVER(TransactionDefinition.PROPAGATION_NEVER),
/**
* 如果当前存在事务,则创建⼀个事务,作为当前事务的嵌套事务来运⾏;
*/
NESTED(TransactionDefinition.PROPAGATION_NESTED);
2.2 SpringBoot 事务实现
首先通过 @EnableTransactionManagement 注解会为容器倒入一个 TransactionManagementConfigurationSelector 的选择器,也就是对事务的自动配置,会为需要事务处理的对象生成代理对象,通过拦截器 TransactionInterceptor 拦截进行调用,主要会进入拦截器的 invoke 方法。
@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
很明显可以看出,就是通过 AOP 对于方法进行增强,调用 invokeWithinTransaction 添加事务操作。
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final TransactionAspectSupport.InvocationCallback invocation) throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
final TransactionManager tm = determineTransactionManager(txAttr);
// 省略响应式编程的事务操作
PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
// 根据传播级别判断是否需要创建事务
TransactionAspectSupport.TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
Object retVal;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// 拦截链的放行
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
if (retVal != null && vavrPresent && TransactionAspectSupport.VavrDelegate.isVavrTry(retVal)) {
// Set rollback-only in case of Vavr failure matching our rollback rules...
TransactionStatus status = txInfo.getTransactionStatus();
if (status != null && txAttr != null) {
retVal = TransactionAspectSupport.VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
}
}
// 最后判断是否提交
commitTransactionAfterReturning(txInfo);
return retVal;
} else {
Object result;
final TransactionAspectSupport.ThrowableHolder throwableHolder = new TransactionAspectSupport.ThrowableHolder();
// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
try {
result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {
TransactionAspectSupport.TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
try {
Object retVal = invocation.proceedWithInvocation();
if (retVal != null && vavrPresent && TransactionAspectSupport.VavrDelegate.isVavrTry(retVal)) {
// Set rollback-only in case of Vavr failure matching our rollback rules...
retVal = TransactionAspectSupport.VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
}
return retVal;
}
catch (Throwable ex) {
if (txAttr.rollbackOn(ex)) {
// A RuntimeException: will lead to a rollback.
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
}
else {
throw new TransactionAspectSupport.ThrowableHolderException(ex);
}
}
else {
// A normal return value: will lead to a commit.
throwableHolder.throwable = ex;
return null;
}
}
finally {
cleanupTransactionInfo(txInfo);
}
});
}
// 省略大量异常的处理
return result;
3. 过滤器 (Filter) 和 拦截器 (Interceptor)
过滤器 和 拦截器 均体现了AOP的编程思想。
不同点:
- 实现原理:
- 过滤器 是基于函数回调的;
- 拦截器 则是基于Java的反射机制(动态代理)实现的。
- 使用范围:
- 过滤器Filter 的使用要依赖于Tomcat等容器,导致它只能在web程序中使用。
- 拦截器(Interceptor) 它是一个Spring组件,并由Spring容器管理,并不依赖Tomcat等容器,是可以单独使用的。
- 触发时机不同:
- 过滤器Filter是在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在servlet处理完以后。
- 拦截器 Interceptor 是在请求进入servlet后,在进入Controller之前进行预处理的,Controller 中渲染了对应的视图之后请求结束。