spring的理解与其注解的分析
1. 首先理解一下事务是如何被代理的。
我们只需要在springboot启动类上加一个注解,然后在方法上加上,那么该方法在出现异常的时候就会进行回滚,那么此时有几个需要我们来解答以下。
问题1: 为什么我们在获取的时候会获取到一个代理对象?
问题2: 代理对象什么时候生成的?
问题3: 代理对象存放在哪里?
接下来会一一进行回答。
首先查看方法调用 context.getBean("")。 可以发现他调用了doGetBean方法,然后调用了 getSingleton方法,最终定位在了 singletonObjects 这个map中,
其是一个单例缓存池,key:beanName value:单例对象
此时会引出一个常见的面试题:spring 是如何解决循环依赖的问题。
这个先不讲,等以后在讲。
那我们进行get的时候,那么就一定会有一个方法对这个map进行一个put操作。
此时通过方法的查找,发现有一个有一个方法: 增加单例模式
这个方法只是往上走的话,找到getSingleton方法, 再往上找的话会找到doGetBean方法。
dogetBean会有两次获取getSingleton的方法,刚启动的时候调用的话,此时肯定返回的肯定是null。
那么第二次调用的时候,代码如下: 这个方法是从单例缓存池中获取对象,如果没获取对象,就会调用singletonFactory.getObject();
此时就相当于调用createBean()方法, 因其是一个函数式接口,可以使用lamda表达式,所以当前版本不是一个工厂,而是一个lamda表达式。
createBean中有一行代码: resolveBeforeInstantiation() 通过bean的后置处理器来及墨西哥后置处理生成代理对象。但是这里不会生成代理对象,
因为真实的对象并没有生成。
往下走的话,会遇到这一句话 doCreateBean() 方法,该步骤是我们真正创建bean实例对象的过程。
那么doCreateBean中有两行代码比较重要
1. 通过推断构造函数,使用合适的实例化策略来创建新的实例。
2. populateBean是先给对象进行赋值,然后在给对象进行初始化操作(这里生成了代理对象)
我们再进入initializeBean这个方法。
这个方法有三个流程:
1. 在初始化之前调用bean的后置处理器的postProcessorsBeforeInitialization 方法
2. 调用初始化方法
3. 调用bean的后置处理器的PostProcessorsAfterInitialization方法
在后置处理器的after方法返回了代理对象。
那么就可以知道,代理对象是在BeanPostProcessors.after方法生成的代理对象。
此时线索断了,不知道是哪个后置处理器搞的事,那么就要从开启代理对象的注解开始进行分析,这个注解是 @EnableTransactionManagement。
这个注解详细信息:
@Import注解可以为我们容器中导入组件 ----> TransactionManagementConfigurationSelector 。
我们点进去这个类:
其中selectImports会被回调,方法的返回值是我们需要导入类的全类名路径,然后这个类就会被加载到容器中。
一般默认是PROXY这个选项:
此时导入两个类:AutoProxyRegistrar 和ProxyTransactionManagementConfiguration
点进去AutoProxyRegistrar这个类:其实现了这个接口 ImportBeanDefinitionRegistrar这个接口
这个类也会被回调,会导入InfrastructureAdvisorAutoProxyCreator 创建器
这个类实现了BeanPostProcessor这个方法, 此时又可以玩下去了,因为找到了一个和事务相关的后置处理器。这个方法在其父类中:
在该后置方法中,我们的事务和aop对象就是在这里生成的。
那么开始分析wrapIfNecessary这个方法,找到了这个方法:
那么其中的advisor从哪来的呢?
我们找到另外一个类:ProxyTransactionManagementConfiguration :
其有一个adivsor,叫BeanFactoryTransactionAttributeSourceAdvisor和TranactionAttributeSource
这两个组件就是用来解析它的,通过匹配,发现如果有advisor被匹配上了,就会返回该advisor。
当找到一个的时候此时就会找到真正创建代理对象的地方。
进去这个方法,会调用到这个下面这个方法:
因此可以在注解上加上proxyTargetClass = true 强制走CGlib代理。
此时代理对象创建完成。
但其实还有一个类也被注入其中: 该类为 TransactionInterceptor类,其继承自MethodInterceptor。所以需要从其invoke开始
具体的事务处理工作交给了这个Interceptor进行完成。
主要看其invoke方法。
接下来讲一讲spring的IOC和AOP的理解。
IOC意思是 Inversion of control (控制反转),其实现方法是通过DI(dependency injection)依赖注入实现的。将对象交给Spring容器去管理,谁需要某个类的时候进行注入就可以了。
其主要为了降低类之间的耦合度,并且不用每次在new出一个对象出来。
AOP面向切面编程
其主要是将程序中的交叉业务逻辑,封装成一个切面,然后注入到目标对象中。 通过代理的方式来实现,这样可以提高程序的内聚性。