第1节 代理对象创建

1.1 AOP基础用例准备

Bean定义

  1. @Component
  2. public class LagouBean {
  3. public void tech(){
  4. System.out.println("java learning......");
  5. }
  6. }

Aspect定义

定义横切逻辑

  1. @Component
  2. @Aspect
  3. public class LagouAspect {
  4. @Pointcut("execution(* com.lagou.*.*(..))")
  5. public void pointcut(){
  6. }
  7. @Before("pointcut()")
  8. public void before() {
  9. System.out.println("before method ......");
  10. }
  11. }

测试用例

  1. /**
  2. *测试用例:Aop 代理对象创建
  3. */
  4. @Test
  5. public void testAopProxyBuild(){ ApplicationContext applicationContext = new
  6. AnnotationConfigApplicationContext(SpringConfig.class);
  7. LagouBean lagouBean = applicationContext.getBean(LagouBean.class); lagouBean.tech();
  8. }




1.2 时机点分析

先来判断一下,在去获取单例对象时,代理对象是否产生?
image.png
value里面都是 CglibAopProxy代理对象
我们发现在 getBean 之前,LagouBean对象已经产生(即在第一行初始化代码中完成),而且该对象是一个代理对象(Cglib代理对象),我们断定,容器初始化过程中目标Bean已经完成了代理,返回了代理对象

那么代理对象产生了,那他是如何产生的呢?他的创建过程是如何的呢?

1.3 代理对象创建流程


若想在源码当中引入aop,首先使用第三方的jar引入到build.gradle中

  1. plugins {
  2. id 'java'
  3. }
  4. group 'org.springframework'
  5. version '5.1.12.BUILD-SNAPSHOT'
  6. sourceCompatibility = 11
  7. repositories {
  8. mavenCentral()
  9. }
  10. dependencies {
  11. compile(project(":spring-context"))
  12. compile group: 'org.aspectj', name: 'aspectjweaver', version: '1.8.6'
  13. testCompile group: 'junit', name: 'junit', version: '4.12'
  14. }

image.png

然后在当前的工程中写了一个LoginUtils切面类,里面有一个beforeMethod横切逻辑方法
将横切逻辑植入到LagouBean当中,且增加了print方法,

在application.xml中的配置如下

  1. <bean id="lagouBean" class="com.lagou.edu.LagouBean">
  2. </bean>
  3. <!--aop配置-->
  4. <!--横切逻辑-->
  5. <bean id="logUtils" class="com.lagou.edu.LogUtils">
  6. </bean>
  7. <!--切面的配置-->
  8. <aop:config>
  9. <aop:aspect ref="logUtils">
  10. <aop:before method="beforeMethod" pointcut="execution(public void com.lagou.edu.LagouBean.print())"/>
  11. </aop:aspect>
  12. </aop:config>

AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)


这里决定创建代理对象是用JDK Proxy,还是用 Cglib 了,最简单的从使用方面使用来说:设置proxyTargetClass=true强制使用Cglib 代理,什么参数都不设并且对象类实现了接口则默认用JDK 代理,如果对象类没有实现接口则也必须用Cglib代理

AOP源码分析类方法调用关系课堂讲解过程中记录
image.png

动态代理,只有bean实例化之后了,那么bean后后置处理之后了

1、给前后置处理器都打断点,并设置过滤条件

image.png

2、根据xml中配置id来设置条件

image.png

3、当代码停在断点此处image.png

4、看在处理器里面的情况

image.png

image.png

image.png

BeanPostProcessor bean 的处理器里面实现类是有动态代理类的。
image.png

image.png

image.png
image.png
image.png
image.png
image.png
image.png
image.png

image.png

image.png

image.png

image.png

时序图:
AOP的动态代理.jpg

注意:
这里我用了相互依赖的两个Bean进行测试,发现只有实例B先进来。实例A是后进来的
虽然能进去,但是不符合代理的条件。(存在循环依赖是不符合代理条件的,怎么进都进不去)
只有单例bean才可以。
image.png
image.png

第2节 Spring声明式事务控制


声明式事务很方便,尤其纯注解模式,仅仅几个注解就能控制事务了思考:这些注解都做了什么?好神奇! @EnableTransactionManagement
@Transactional

2.1 @EnableTransactionManagement

@EnableTransactionManagement 注解使用
@Import 标签引入了TransactionManagementConfigurationSelector类,
这个类又向容器中导入了两个重要的组件

2.2 加载事务控制组件


AutoProxyRegistrar
AutoProxyRegistrar 类的 registerBeanDefinitions 方法中又注册了一个组件
进入 AopConfigUtils.registerAutoProxyCreatorIfNecessary 方法


发现最终,注册了一个叫做 InfrastructureAdvisorAutoProxyCreator 的 Bean,而这个类是 AbstractAutoProxyCreator 的子类,实现了 SmartInstantiationAwareBeanPostProcessor 接口

public class InfrastructureAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator

public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport

implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware


继承体系结构图如下



它实现了SmartInstantiationAwareBeanPostProcessor,说明这是一个后置处理器,而且跟 spring AOP 开启@EnableAspectJAutoProxy 时注册的 AnnotationAwareAspectJProxyCreator实现的是同一个接口,所以说,声明式事务是 springAOP 思想的一种应用

ProxyTransactionManagementConfiguration 组件


ProxyTransactionManagementConfiguration是一个容器配置类,注册了一个组件transactionAdvisor,称为事务增强器,然后在这个事务增强器中又注入了两个属性:transactionAttributeSource,即属性解析器transactionAttributeSource 和 事务拦截器 transactionInterceptor


属性解析器 AnnotationTransactionAttributeSource 部分源码如下

属性解析器有一个成员变量是annotationParsers,是一个集合,可以添加多种注解解析器(TransactionAnnotationParser),我们关注 Spring 的注解解析器,部分源码如下

属性解析器的作用之一就是用来解析@Transaction注解


TransactionInterceptor 事务拦截器,部分源码如下
上述组件如何关联起来的?

事务拦截器实现了MethodInterceptor接口,追溯一下上面提到的InfrastructureAdvisorAutoProxyCreator后置处理器,它会在代理对象执行目标方法的时候获取其拦截器链,而拦截器链就是这个TransactionInterceptor,这就把这两个组件联系起来;

构造方法传入PlatformTransactionManager(事务管理器)、TransactionAttributeSource(属性解析器),但是追溯一下上面贴的ProxyTransactionManagementConfiguration的源码,在注册事务拦截器的时候并没有调用这个带参构造方法,而是调用的无参构造方法,然后再调用set方法注入这两个属性,效果一样。

invokeWithinTransaction 方法,部分源码如下(关注1、2、3、4 标注处)


声明式事务分析课堂讲解过程中记录

EnableTransactionManagement 注解

1)通过@import引入了TransactionManagementConfigurationSelector类它的selectImports方法导入了另外两个类:AutoProxyRegistrar和

ProxyTransactionManagementConfiguration

2)AutoProxyRegistrar类分析

方法registerBeanDefinitions中,引入了其他类,通过

AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)引入

**

它继承了AbstractAutoProxyCreator,是一个

后置处理器类

3)ProxyTransactionManagementConfiguration 是一个添加了@Configuration注解的配置类

(注册bean)

注册事务增强器(注入属性解析器、事务拦截器)

属性解析器:AnnotationTransactionAttributeSource,内部持有了一个解析器集合

Set annotationParsers; 具体使用的是SpringTransactionAnnotationParser解析器,用来解析

@Transactional的事务属性

事务拦截器:TransactionInterceptor实现了MethodInterceptor接口,该通用拦截会在产生代理对象之前和aop增强合并,最终一起影响到代理对象

TransactionInterceptor的invoke方法中invokeWithinTransaction会触发原有业务逻辑调用(增强事务)