第1节 代理对象创建
1.1 AOP基础用例准备
Bean定义
@Componentpublic class LagouBean {public void tech(){System.out.println("java learning......");}}
Aspect定义
定义横切逻辑
@Component@Aspectpublic class LagouAspect {@Pointcut("execution(* com.lagou.*.*(..))")public void pointcut(){}@Before("pointcut()")public void before() {System.out.println("before method ......");}}
测试用例
/***测试用例:Aop 代理对象创建*/@Testpublic void testAopProxyBuild(){ ApplicationContext applicationContext = newAnnotationConfigApplicationContext(SpringConfig.class);LagouBean lagouBean = applicationContext.getBean(LagouBean.class); lagouBean.tech();}
1.2 时机点分析
先来判断一下,在去获取单例对象时,代理对象是否产生?
 
value里面都是 CglibAopProxy代理对象
我们发现在 getBean 之前,LagouBean对象已经产生(即在第一行初始化代码中完成),而且该对象是一个代理对象(Cglib代理对象),我们断定,容器初始化过程中目标Bean已经完成了代理,返回了代理对象。
 
那么代理对象产生了,那他是如何产生的呢?他的创建过程是如何的呢?
1.3 代理对象创建流程
 
若想在源码当中引入aop,首先使用第三方的jar引入到build.gradle中
plugins {id 'java'}group 'org.springframework'version '5.1.12.BUILD-SNAPSHOT'sourceCompatibility = 11repositories {mavenCentral()}dependencies {compile(project(":spring-context"))compile group: 'org.aspectj', name: 'aspectjweaver', version: '1.8.6'testCompile group: 'junit', name: 'junit', version: '4.12'}

然后在当前的工程中写了一个LoginUtils切面类,里面有一个beforeMethod横切逻辑方法
将横切逻辑植入到LagouBean当中,且增加了print方法,
在application.xml中的配置如下
<bean id="lagouBean" class="com.lagou.edu.LagouBean"></bean><!--aop配置--><!--横切逻辑--><bean id="logUtils" class="com.lagou.edu.LogUtils"></bean><!--切面的配置--><aop:config><aop:aspect ref="logUtils"><aop:before method="beforeMethod" pointcut="execution(public void com.lagou.edu.LagouBean.print())"/></aop:aspect></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源码分析类方法调用关系课堂讲解过程中记录
动态代理,只有bean实例化之后了,那么bean后后置处理之后了
1、给前后置处理器都打断点,并设置过滤条件

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

3、当代码停在断点此处
4、看在处理器里面的情况



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












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

第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
 
@Transactional的事务属性
 
事务拦截器:TransactionInterceptor实现了MethodInterceptor接口,该通用拦截会在产生代理对象之前和aop增强合并,最终一起影响到代理对象
 
TransactionInterceptor的invoke方法中invokeWithinTransaction会触发原有业务逻辑调用(增强事务)
