第1节 代理对象创建
1.1 AOP基础用例准备
Bean定义
@Component
public class LagouBean {
public void tech(){
System.out.println("java learning......");
}
}
Aspect定义
定义横切逻辑
@Component
@Aspect
public class LagouAspect {
@Pointcut("execution(* com.lagou.*.*(..))")
public void pointcut(){
}
@Before("pointcut()")
public void before() {
System.out.println("before method ......");
}
}
测试用例
/**
*测试用例:Aop 代理对象创建
*/
@Test
public void testAopProxyBuild(){ ApplicationContext applicationContext = new
AnnotationConfigApplicationContext(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 = 11
repositories {
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会触发原有业务逻辑调用(增强事务)