前些日子把Spring AOP的源码撸了几遍,但是回过头总发现会忘记,因此以这篇文章记录一下,当作是总结和复习!
1 什么是AOP
AOP(Aspect Oriented Programming), 中文翻译过来就是面向切面编程,AOP可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善,OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力,也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
简单的说,AOP允许你在执行某个方法前,执行方法后,或者异常抛出后等,执行你希望进行的操作,就是执行你自定义的一部分代码,而这些操作是动态织入的,完全是已一种非入侵式的方式进行的,在不修改源代码的情况下加入你自己的增强处理,这就叫“横切”
2 Spring AOP 的基本概念
-
Aspect(切面):切面用于组织多个Advice,通常是一个类,里面可以定义Pointcut和Advice
-
JoinPoint(连接点):程序执行过程中明确的点,如方法的调用,异常的抛出,在Spring AOP中,连接点总是方法的调用
-
Advice(增强处理):AOP在切入点进行的增强处理,有前置,后置,返回,异常,环绕增强
-
Pointcut(切入点):可以插入增强处理的连接点,在程序中主要体现为书写切入点表达式, 简单的说,就是当某特定连接点满足要求时,该连接点被添加增强处理,该连接点就变成了切入点
-
目标对象:被AOP框架进行增强处理的对象
-
AOP代理:AOP框架创建的增强对象,简单的说,代理就是对目标对象的增强,Spring AOP可以使用JDK动态代理和Cglib动态代理,前者基于接口,后者基于子类
-
织入:将增强处理添加到目标对象中
增强处理类型
- 前置增强处理:在我们执行目标方法之前运行(@Before)
- 后置增强处理:在我们目标方法运行结束之后 ,不管有没有异常(@After)
- 返回增强处理:在我们的目标方法正常返回值后运行(@AfterReturning)
- 异常增强处理:在我们的目标方法出现异常后运行(@AfterThrowing)
- 环绕增强处理:动态代理, 需要手动执行joinPoint.procced()(其实就是执行我们的目标方法执行之前相当于前置通知, 执行之后就相当于我们后置通知(@Around)
3 Spring AOP的基本使用方式,基于注解
Spring AOP也有基于XML的配置方式,但是Spring发展到现在,已经很少有基于XML的方式去使用Spring AOP甚至Spring体系的了,现在基本都是使用“零配置”,即注解的方式去使用,所以本片内容将不再讨论关于XML配置Spring AOP的相关知识
3.1 定义目标类(目标类)
package com.mingweicai.intergration.springaop;
public class BusinessService {
public int mainLogic(int parameter){
System.out.println("------mainLogic------");
return parameter;
}
public int mainLogicWithException(int parameter){
System.out.println("------mainLogicWithException------");
throw new RuntimeException("unknowException");
}
}
3.2 定义切面,切入点,和增强处理
@Aspect
public class LogAspect {
@Pointcut("execution(public int com.mingweicai.intergration.springaop.BusinessService.*(..))")
public void pointCut(){}
/**
* 前置增强
*/
@Before("pointCut()")
public void logStart(){
System.out.println("------@Before: 前置通知日志------");
}
/**
* 后置增强
*/
@After("pointCut()")
public void logEnd(){
System.out.println("------@After: 后置通知日志------");
}
/**
* 返回增强
* 只有方法成功返回才会执行
* @param result
*/
@AfterReturning(value = "pointCut()", returning = "result")
public void logReturn(Object result){
System.out.println("------@AfterReturning: 方法执行完毕,结果是 "+ result +"------");
System.out.println();
}
/**
* 异常增强
*/
@AfterThrowing(value = "pointCut()",throwing = "t")
public void logException(Throwable t){
System.out.println("------@AfterThrowing: 运行异常......异常信息是" + t);
}
/**
* 环绕增强
*/
@Around("pointCut()")
public Object Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("------@Around: 执行目标方法之前...------");
Object obj = proceedingJoinPoint.proceed();//相当于开始调div地
System.out.println("------@Around: 执行目标方法之后...------");
return obj;
}
}
切面:LogAspect 为一个切面类
切入点pointCut():表达式"execution(public int com.mingweicai.intergration.springaop.BusinessService.*(…))"指定BusinessService的所有方法调用为切入点
增强处理:@Before,@After等标记的方法内定义了增强处理逻辑,指定pointCut()切入点,即BusinessService所有方法调用前,调用后等…执行增强处理逻辑
3.3 Spring配置类
@Configuration
@EnableAspectJAutoProxy
public class BeanConfiguration {
@Bean
public BusinessService createBusinessService(){
return new BusinessService();
}
@Bean
public LogAspect createLogAspects(){
return new LogAspect();
}
}
3.4 测试类
public class Main {
public static void main(String args[]){
AnnotationConfigApplicationContext configApplicationContext =
new AnnotationConfigApplicationContext(BeanConfiguration.class);
BusinessService service = configApplicationContext.getBean(BusinessService.class);
service.mainLogic();
service.mainLogicWithException();
configApplicationContext.close();
}
}
3.5 测试结果
------@Around: 执行目标方法之前...------
------@Before: 前置通知日志------
------mainLogic------
------@Around: 执行目标方法之后...------
------@After: 后置通知日志------
------@AfterReturning: 方法执行完毕,结果是 1------
------@Around: 执行目标方法之前...------
------@Before: 前置通知日志------
------mainLogicWithException------
------@After: 后置通知日志------
------@AfterThrowing: 运行异常......异常信息是java.lang.RuntimeException: unknowException
Exception in thread "main" java.lang.RuntimeException: unknowException
at com.mingweicai.intergration.springaop.BusinessService.mainLogicWithException(BusinessService.java:12)
总结一下各个增强处理的处理顺序
方法没有抛出异常时
@Around -> @Before -> 方法原始逻辑 -> @Around -> @After
方法抛出异常时
@Around -> @Before -> 方法原始逻辑 -> @After -> @AfterThrowing
当方法抛出异常时,@AfterReturning增强处理就失效了
3.5 在增强处理中获取方法参数,目标对象等
访问目标方法最简单的方法就是定义增强处理方法时将第一个参数定义为JoinPoint类型,在JoinPoint代表增强处理时的连接点,JoinPoint中包含以下几个常用的方法
- Object[] getArgs() : 返回执行目标方法时的参数列表
- Signature getSignature() :返回被增强处理的方法的相关信息
- Object getTarget() :返回目标对象
- Object getThis() : 返回生成的代理对象
以一个例子来说明
定义增强
@Aspect
public class FourAdviceAspect {
@Pointcut("execution(public int com.mingweicai.intergration.springaop.demo2.BusinessService.*(..))")
public void pointCut(){}
/**
* 前置增强
*/
@Before("pointCut()")
public void before(JoinPoint joinPoint){
System.out.println("------@Before: 模拟执行权限检查------");
System.out.println("------@Before: 执行的方法名"+ joinPoint.getSignature().getName() +"------");
System.out.println("------@Before: 方法执行的参数"+ Arrays.toString(joinPoint.getArgs()) +"------");
System.out.println("------@Before: 目标对象"+ joinPoint.getTarget() +"------");
}
/**
* 后置增强
*/
@After("pointCut()")
public void after(JoinPoint joinPoint){
System.out.println("------@After: 方法结束后释放资源------");
System.out.println("------@After: 执行的方法名"+ joinPoint.getSignature().getName() +"------");
System.out.println("------@After: 方法执行的参数"+ Arrays.toString(joinPoint.getArgs()) +"------");
System.out.println("------@After: 目标对象"+ joinPoint.getTarget() +"------");
}
/**
* 返回增强
* 只有方法成功返回才会执行
* @param result
*/
@AfterReturning(value = "pointCut()", returning = "result")
public void logReturn(JoinPoint joinPoint,Object result){
System.out.println("------@AfterReturning: 方法结束后释放资源------");
System.out.println("------@AfterReturning: 执行的方法名"+ joinPoint.getSignature().getName() +"------");
System.out.println("------@AfterReturning: 方法执行的参数"+ Arrays.toString(joinPoint.getArgs()) +"------");
System.out.println("------@AfterReturning: 目标对象"+ joinPoint.getTarget() +"------");
System.out.println("------@AfterReturning: 方法执行的结果"+ joinPoint.getTarget() +"------");
}
/**
* 环绕增强
* @param proceedingJoinPoint
* @return
* @throws Throwable
*/
@Around("pointCut()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("------@Around: 执行目标方法之前, 模拟开始事务...------");
Object args[] = proceedingJoinPoint.getArgs();
if(args != null && args.length > 0 && args[0].getClass() == String.class){
// 修改目标方法中的第一个参数
args[0] = "[增加的前缀]:" + args[0];
}
Object obj = proceedingJoinPoint.proceed(args);//相当于开始调div地
System.out.println("------@Around: 执行目标方法之后, 模拟结束事务...------");
if(obj != null && obj instanceof Integer){
obj = (Integer) obj * (Integer) obj;
}
return obj;
}
}
目标类
public class BusinessService {
public int mainLogic(String param){
System.out.println(param);
return 4;
}
}
测试
public class Main {
public static void main(String args[]){
AnnotationConfigApplicationContext configApplicationContext =
new AnnotationConfigApplicationContext(BeanConfiguration.class);
BusinessService service = configApplicationContext.getBean(BusinessService.class);
service.mainLogic("执行主方法");
configApplicationContext.close();
}
}
结果
------@Around: 执行目标方法之前, 模拟开始事务...------
------@Before: 模拟执行权限检查------
------@Before: 执行的方法名mainLogic------
------@Before: 方法执行的参数[[增加的前缀]:执行主方法]------
------@Before: 目标对象com.mingweicai.intergration.springaop.demo2.BusinessService@59af0466------
[增加的前缀]:执行主方法
------@Around: 执行目标方法之后, 模拟结束事务...------
------@After: 方法结束后释放资源------
------@After: 执行的方法名mainLogic------
------@After: 方法执行的参数[[增加的前缀]:执行主方法]------
------@After: 目标对象com.mingweicai.intergration.springaop.demo2.BusinessService@59af0466------
------@AfterReturning: 方法结束后释放资源------
------@AfterReturning: 执行的方法名mainLogic------
------@AfterReturning: 方法执行的参数[[增加的前缀]:执行主方法]------
------@AfterReturning: 目标对象com.mingweicai.intergration.springaop.demo2.BusinessService@59af0466------
------@AfterReturning: 方法执行的结果16------
4 Spring AOP源码详解
4.3.1 Spring AOP 入口
熟悉Spring的朋友应该知道,如果我们要开启Spring AOP的功能,那么只要在启动处加上@EnableAspectJAutoProxy即可
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
如上,@EnableAspectJAutoProxy标签被@Import(AspectJAutoProxyRegistrar.class)标签标记,AspectJAutoProxyRegistrar 中如下代码将在启动时被执行
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AspectJAutoProxyRegistrar将以AnnotationAwareAspectJAutoProxyCreator这个类为目标定义一个BeanDefinition放到spring容器中, 这是通过实现ImportBeanDefinitionRegistrar接口来装载的,那么在项目启动后,Spring IOC容器中会存在AnnotationAwareAspectJAutoProxyCreator类的一个单例对象对象实例
话不多说,看看AnnotationAwareAspectJAutoProxyCreator的类继承结构
AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessor接口,BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口,声明如下
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
了解Spring的人都知道,在Spring对bean初始化完成之后,会调用BeanPostProcessor的postProcessAfterInitialization方法,Spring AOP就是在这个方法里面根据传递进来的目标对象生成代理对象并返回的,那么我们可以从AnnotationAwareAspectJAutoProxyCreator实现的postProcessAfterInitialization作为入口点,一步步分析Spring AOP时如何实现“切面编程的”
4.3.2 Spring AOP 主逻辑
依照个人理解,Spring AOP源码的大体流程如下
- 从TargetSource缓存中查找代理对象,如果找到,直接返回,否则继续往下执行
- 从缓存中判断该对象是否已经标记为不应该被代理,如果是,直接返回,否则,继续往下执行
- 解析Advisor(Advisor是持有切入点和增强处理定义的一个基础接口,下层有很多实现),这里的主要逻辑其实是找出所有被@Aspect或者xml中配置的切面,解析每个被增强标签标注(例@Before)的方法并封装成Advisor返回
- 过滤适合的Advisor,得到一个Advisor列表,如果没有适配的Advisor,那么直接返回,标记该对象不应被代理
- 通过解析得到的Advisor,创建代理对象(JDK动态代理或者CGLIB动态代理)
- 返回代理对象
那么直接从入口处一步步追踪AOP源码
AbstractAutoProxyCreator
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
// 根据给定的bean的class和name构建出一个key,格式beanClassName_beanName
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 如果合适被代理,则需要封装指定bean
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object getCacheKey(Class<?> beanClass, @Nullable String beanName) {
if (StringUtils.hasLength(beanName)) {
return (FactoryBean.class.isAssignableFrom(beanClass) ?
BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
}
else {
return beanClass;
}
}
AbstractAutoProxyCreator
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 在targetSourcedBeans集合中有缓存的代理对象则直接返回
// 解析targetsource的源码在postProcessBeforeInitialization中
// 有兴趣的话可以google一下targetsource的作用和使用方式,一般情况下不使用Targetsorce,所以这里targetSourcedBeans为空
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// advisedBeans 集合中标记该对象不该被代理,直接返回
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 是Advice Pointcut Advisor AopInfrastructureBean 类的子类
// beanName以 ORIGINAL 结尾
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 寻找Advisor列表
// Advisor是持有切入点和增强处理定义的一个基础接口,下层有很多实现
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
// 标记该bean应该被代理
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 真正创建代理对象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
// 缓存proxy类型
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
// 标记该bean对象不应该被代理
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 抽象方法,交由子类具体实现
@Nullable
protected abstract Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,
@Nullable TargetSource customTargetSource) throws BeansException;
上面的代码虽然看起来简单,但是每个步骤中都经历了大量复杂的逻辑,首先来看看增强方法获取的实现逻辑
AbstractAdvisorAutoProxyCreator
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
// 继续调用findEligibleAdvisors(beanClass, beanName)进行查找
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
// 如果advisors列表是空,那么返回null,表示不代理
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
// 如果advisors不是空,那么转化为数组返回
return advisors.toArray();
}
AbstractAdvisorAutoProxyCreator
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 寻找所有Advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 找出匹配的Advisor
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 扩展Advisor
extendAdvisors(eligibleAdvisors);
// 对Advisor进行排序
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
findCandidateAdvisors()方法在 子类AbstractAdvisorAutoProxyCreator 和 AnnotationAwareAspectJAutoProxyCreator 都有实现,由于我们分析的是基于注解进行的的AOP,所以它的实现其实是由AnnotationAwareAspectJAutoProxyCreator 类来完成的,我们继续跟踪这个类的方法
AnnotationAwareAspectJAutoProxyCreator
@Override
protected List<Advisor> findCandidateAdvisors() {
// 调用父类的findCandidateAdvisors方法
// 当使用注解方式配置AOP是并不是丢弃了对XML配置的支持,这里调用父类方法加载xm配置文件中的AOP声明
// Add all the Spring advisors found according to superclass rules.
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
// 真正查找Advisor的逻辑在这个地方
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
AnnotationAwareAspectJAutoProxyCreator间接继承了AbstractAdvisorAutoProxyCreator,在实现获取增强方法中除了保留父类获取配置文件中定义的增强外,同时添加了获取Bean的注解怎个强的功能,那么其是委托给
BeanFactoryAspectJAdvisorsBuilder 这个类的buildAspectJAdvisors方法实现的
AbstractAdvisorAutoProxyCreator
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
return this.advisorRetrievalHelper.findAdvisorBeans();
}
/**
* Find all eligible Advisor beans in the current bean factory,
* ignoring FactoryBeans and excluding beans that are currently in creation.
* @return the list of {@link org.springframework.aop.Advisor} beans
* @see #isEligibleBean
*/
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
String[] advisorNames = this.cachedAdvisorBeanNames;
// 在Spring IOC容器中寻找Advisor类型对象的对象名
if (advisorNames == null) {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
// 一般都是0,所以直接返回
if (advisorNames.length == 0) {
return new ArrayList<>();
}
... 略 ...
...
return advisors;
}
4.3.3 解析增强器Advisor
解析Advisor的工作交由BeanFactoryAspectJAdvisorsBuilder类的实例对象完成
在真正研究这个方法的代理之前,先整理一下逻辑思路
- 获取Spring IOC容器中所有的beanName,通过BeanFactory提取出来
- 遍历所有beanName, 找出生命AspectJ注解的类,进行进一步的处理
- 对标记为AspectJ注解的类进行增强器的获取
- 将提取结果加入缓存
BeanFactoryAspectJAdvisorsBuilder
public List<Advisor> buildAspectJAdvisors() {
// 第一次初始化的话,aspectNames为空
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
// 加锁,防止线程安全问题
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
// 从Spring IOC容器中获取Object类型的所有beanName,由于Java中所有对象都继承Object,所以获取出来的为Spring IOC容器的所有对象
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
// 根据beanNames进行遍历
for (String beanName : beanNames) {
// 判断是否是合格的bean,一般都是true
if (!isEligibleBean(beanName)) {
continue;
}
// We must be careful not to instantiate beans eagerly as in this case they
// would be cached by the Spring container but would not have been weaved.
// 获取类的类型对象
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
// 如果对象切面类型对象,即类是否被@Aspect标签标记
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
// 新建AspectMetadata对象,存储对象类型和对象名称信息
AspectMetadata amd = new AspectMetadata(beanType, beanName);
// 一般情况下kind都是PerClauseKind.SINGLETON类型
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
// MetadataAwareAspectInstanceFactory 保存有beanFactory和AspectMetadata信息
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
// 真正获取Advisor的逻辑在这个地方
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
// 如果目标bean是单例对象,缓存classAdvisors
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
else {
// 如果目标对象不是单例bean,缓存factory
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
// 加入缓存中
List<Advisor> advisors = new ArrayList<>();
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
完成Advisor提取的功能委托给了ReflectiveAspectJAdvisorFactory 的getAdvisors(factory)方法来实现
ReflectiveAspectJAdvisorFactory
@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
// 获取标记为AspectJ的类
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
// 获取标记为AspectJ的name
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
validate(aspectClass);
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
// so that it will only instantiate once.
// 使用装配者模式装配MetadataAwareAspectInstanceFactory
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
// 真正获取Advisor的逻辑在这个地方
List<Advisor> advisors = new ArrayList<>();
// getAdvisorMethods方法获取被@Before, @After, @Around, @AfterReturning标签标记的方法(Method)
// @PointCut方法将不被处理
for (Method method : getAdvisorMethods(aspectClass)) {
//真正创建Advisor的地方
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// If it's a per target aspect, emit the dummy instantiating aspect.
// 如果寻找的增强其不为空并且配置了增强延迟初始化那么需要在首位加入同步实例化增强器
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
// Find introduction fields.
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
ReflectiveAspectJAdvisorFactory
@Override
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
// 验证是否是切面对象
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
// 寻找pointcut
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
// 创建Advisor实例对象
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
ReflectiveAspectJAdvisorFactory
切点信息的获取,所有获取切点信息就是只注解的表达式信息的获取,如@Before("test()“), 获取出来的表达式是test()
@Nullable
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
// 获取方法上的注解对象
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// 使用AspectJExpressionPointcut实例来封装获取的信息
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
// 日趋到的注解中的表达式
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
return ajexp;
}
AbstractAspectJAdvisorFactory
private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
@SuppressWarnings("unchecked")
@Nullable
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
AbstractAspectJAdvisorFactory
@Nullable
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
A result = AnnotationUtils.findAnnotation(method, toLookFor);
if (result != null) {
return new AspectJAnnotation<>(result);
}
else {
return null;
}
}
最后创建的Advisor是InstantiationModelAwarePointcutAdvisorImpl类型对象,真正的切面增强处理其实实在其构造方法里面创建,第一次看源码很容易忽略调这个细节导致蒙头转向,那看看这个实例构造方法做了什么
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
// 一些初始话赋值操作
this.declaredPointcut = declaredPointcut;
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
this.methodName = aspectJAdviceMethod.getName();
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
this.aspectJAdviceMethod = aspectJAdviceMethod;
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
this.aspectInstanceFactory = aspectInstanceFactory;
this.declarationOrder = declarationOrder;
this.aspectName = aspectName;
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
// Static part of the pointcut is a lazy type.
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
// If it's not a dynamic pointcut, it may be optimized out
// by the Spring AOP infrastructure after the first evaluation.
this.pointcut = new PerTargetInstantiationModelPointcut(
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
this.lazy = true;
}
else {
// A singleton aspect.
this.pointcut = this.declaredPointcut;
this.lazy = false;
// 主要的切面创建是在instantiateAdvice这个方法
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
ReflectiveAspectJAdvisorFactory
@Override
@Nullable
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
// 获取到类对象
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
// 创建AspectJAnnotation
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// If we get here, we know we have an AspectJ method.
// Check that it's an AspectJ-annotated class
// 是否是切面类型
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
if (logger.isDebugEnabled()) {
logger.debug("Found AspectJ method: " + candidateAdviceMethod);
}
AbstractAspectJAdvice springAdvice;
// 根据标签类型创建相应的增强器
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
// Now to configure the advice...
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}
这里对应有 AspectJAroundAdvice ,AspectJMethodBeforeAdvice ,AspectJAfterAdvice,AspectJAfterReturningAdvice,AspectJAfterThrowingAdvice分别对应Around,Before, After,AfterReturning,AfterThrowing增强处理
4.3.4 创建代理
自此创建Advisor的逻辑已经完成,回到最初的wrapIfNecessary方法,寻找Advisor方法完成后,那么就真正开始创建代理, 对于代理类的创建和处理,Spring委托给了ProxyFactory去处理,从类名就可以知道,这是一个代理工厂,createProxy主要是一些初始化步骤,这些操作包括如下内容
- 获取当前类中的属性
- 添加代理接口
- 封装Advisor并加入当前ProxyFactory中
- 设置要代理的类
- 当前在Spring中还为子类提供了定制函数customizeProxyFactory,子类可以在此函数中进行对ProxyFactory的进一步封装
- 进行获取代理的操作
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// Proxyfactory用于控制创建代理的对象
ProxyFactory proxyFactory = new ProxyFactory();
// 获取相关属性
proxyFactory.copyFrom(this);
// 决定对于给定的bean是否应该使用targetclass而不是代理接口
// 检查proxyTargetClass和preserveTargetClass属性
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 加入增强器
proxyFactory.addAdvisors(advisors);
// 设置targetSource
proxyFactory.setTargetSource(targetSource);
// 定制代理
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 调用getProxy方法创建代理
return proxyFactory.getProxy(getProxyClassLoader());
}
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
DefaultAopProxyFactory
// 创建代理
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
至此完成了代理的创建,相信了解过Spring AOP的人都听说过Spring是通过cglib动态代理或者jdk动态代理去实现的,网上对于这两种动态代理的介绍到处都是,有兴趣的可以自行google或者百度回顾一下,这里通过源码的方式介绍 一下Spring源码是怎么选择使用这两种方式的
从if判断可以看到有三个条件影响spring的判断
- optimize: 用来控制通过cglib创建的代理是否采用激进的优化策略,除非完全了解Spring AOP的优化策略,否则不建议用户使用这个配置,这个配置仅对cglib动态代理有效,对jdk动态代理无效
- proxyTargetclass:这个属性为true时,目标类本身被代理而不是接口被代理,那么cglib代理将被创建,xml配置方式为<aop:aspectj-autoproxy proxy-target-class=“true”/> , 注解配置方式为@EnableAspectJAutoProxy(proxyTargetClass = true
- hasNoUserSuppliedProxyInterfaces: 是否存在代理接口
总结
- 如果目标对象实现了接口,那么默认使用jdk动态代理
- 如果目标对象实现了接口,可以通过proxyTargetclass属性强制使用cglib动态代理
- 如果目标对象没有实现接口,必须采用cglib库,那么spring会自动在jdk动态代理和cglib动态代理中切换
4.3.4.1 CGLIB动态代理
接下来看一下ObjenesisCglibAopProxy中getProxy方法的实现逻辑
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
// 验证class
validateClassIfNecessary(proxySuperClass, classLoader);
// Configure CGLIB Enhancer...
// 创建及配置Enhancer
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
// 设置拦截器,主要方法
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
// 创建代理类
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
以上函数完整的阐述了一个创建Spring中的Enhancer的过程,读者可以参考Enhancer的文档参考每个步骤的含义
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// Parameters used for optimization choices...
// 对于一些属性的处理
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();
// Choose an "aop" interceptor (used for AOP calls).
// 使用DynamicAdvisedInterceptor作为callback
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
// Choose a "straight to target" interceptor. (used for calls that are
// unadvised but can return this). May be required to expose the proxy.
Callback targetInterceptor;
if (exposeProxy) {
targetInterceptor = (isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
}
else {
targetInterceptor = (isStatic ?
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
}
// Choose a "direct to target" dispatcher (used for
// unadvised calls to static targets that cannot return this).
Callback targetDispatcher = (isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
Callback[] mainCallbacks = new Callback[] {
aopInterceptor, // for normal advice
targetInterceptor, // invoke target without considering advice, if optimized
new SerializableNoOp(), // no override for methods mapped to this
targetDispatcher, this.advisedDispatcher,
new EqualsInterceptor(this.advised),
new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
// If the target is a static one and the advice chain is frozen,
// then we can make some optimizations by sending the AOP calls
// direct to the target using the fixed chain for that method.
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = new HashMap<>(methods.length);
// TODO: small memory optimization here (can skip creation for methods with no advice)
for (int x = 0; x < methods.length; x++) {
Method method = methods[x];
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
this.fixedInterceptorMap.put(method, x);
}
// Now copy both the callbacks from mainCallbacks
// and fixedCallbacks into the callbacks array.
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
this.fixedInterceptorOffset = mainCallbacks.length;
}
else {
callbacks = mainCallbacks;
}
return callbacks;
}
在getCallback中spring考虑了很多情况,但是对于我们来说,我们只需要理解最长用的就可以了,比如将advised属性封装在DynamicAdvisedInterceptor并加入在callbacks中,这么做的目的是什么呢,如何调用呢,我们了解到CGLIB中对于方法的拦截是通过自定义的拦截器(MethodInterceptor接口)加入Callback中并在调用代理是直接激活拦截器中的intercept方法来实现的,那么在getCallback中正是实现了这样一个目的,DynamicAdvisedInterceptor继承自MethodInterceptor,加入Callback中后,在使用代理时调用匹配方法会直接调用DynamicAdvisedInterceptor中的intercept方法,由此推断,对于CGLIB方式实现的代理,核心逻辑肯定在intercept方法中
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
private final AdvisedSupport advised;
public DynamicAdvisedInterceptor(AdvisedSupport advised) {
this.advised = advised;
}
@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 获取拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
// 如果拦截器链为空那么激活原方法
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// We can skip creating a MethodInvocation: just invoke the target directly.
// Note that the final invoker must be an InvokerInterceptor, so we know
// it does nothing but a reflective operation on the target, and no hot
// swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
// 进入拦截器链的调用流程
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
@Override
public boolean equals(@Nullable Object other) {
return (this == other ||
(other instanceof DynamicAdvisedInterceptor &&
this.advised.equals(((DynamicAdvisedInterceptor) other).advised)));
}
/**
* CGLIB uses this to drive proxy creation.
*/
@Override
public int hashCode() {
return this.advised.hashCode();
}
}
4.3.4.2 JDK 动态代理
JdkDynamicAopProxy
@Override
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// Get the interception chain for this method.
// 获取拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
// 如果没有发现任何拦截器,那么直接调用切点方法
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 将拦截器封装在ReflectiveMethodInvocation
// We need to create a method invocation...
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
// 串联调用
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
4.3.5 拦截器链是怎么串联调用的(例CGLIB)
在DynamicAdvisedInterceptor 的intercept方法中,会对Advice进行进一步封装,返回一个新的拦截器(引介增强),这些拦截器继承自MethodInterceptor,不过不要误解,这个MethodInterceptor是Spring AOP定义的,并不是CGLIB中的那个MethodInterceptor
有以下几种类型的引介增强:
- MethodBeforeAdviceInterceptor
- AspectJAfterAdvice
- AfterReturningAdviceInterceptor
- ThrowsAdviceInterceptor
- AspectJAroundAdvice
其中AspectJAfterAdvice 和 AspectJAroundAdvice 本身已经实现了MethodInterceptor接口,所以不用进一步封装
在DynamicAdvisedInterceptor的intercept方法中可以看到,如果拦截器链不为空,那么会新建一个CglibMethodInvocation对象,并调用proceed方法,至此便开始拦截器链的增强处理执行
看看CglibMethodInvocation中proceed方法的实现
proceed的方法主要逻辑如下:
- 从拦截器List链的size - 1下标开始,遍历获取拦截器
- 查看当前拦截器是否符合条件,符合条件的话,调用拦截器的invoke方法进行增强处理
- 如果不符合条件,递归调用proceed方法,遍历拦截器链获取下一个拦截器执行
- 当链遍历完的时候,所有增强处理已经完成,那么调用连接点方法,即执行目标对象原方法
@Override
@Nullable
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
// 遍历获取增强处理
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
假设我们定义了@Before, @Around, @After增强处理,那么最后获取到的增强处理器链是这样的
【AspectJAfterAdvice , MethodBeforeAdviceInterceptor ,AspectJAroundAdvice】
我们先查看AspectJAroundAdvice类的invode方法
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
// 新建ProxyMethodInvocation 和 ProceedingJoinPoint
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
JoinPointMatch jpm = getJoinPointMatch(pmi);
// 激活增强处理方法
return invokeAdviceMethod(pjp, jpm, null, null);
}
}
激活增强处理方法是定义在AbstractAspectJAdvice类中的,每个类激活增强处理方法的时候都使用这个方法
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
Object[] actualArgs = args;
if (this.aspectJAdviceMethod.getParameterCount() == 0) {
actualArgs = null;
}
try {
// 使用反射,激活增强处理方法
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
// TODO AopUtils.invokeJoinpointUsingReflection
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("Mismatch on arguments to advice method [" +
this.aspectJAdviceMethod + "]; pointcut expression [" +
this.pointcut.getPointcutExpression() + "]", ex);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
那么Around增强处理方法被执行,一般我们around增强处理方法定义如下
@Around("pointCut()")
public Object Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("------@Around: 执行目标方法之前...------");
Object obj = proceedingJoinPoint.proceed();//相当于开始调div地
System.out.println("------@Around: 执行目标方法之后...------");
return obj;
}
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private final MethodBeforeAdvice advice;
/**
* Create a new MethodBeforeAdviceInterceptor for the given advice.
* @param advice the MethodBeforeAdvice to wrap
*/
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// 调用增强方法
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
// 继续下一步增强处理
return mi.proceed();
}
}
在MethodBeforeAdviceInterceptor中,在执行完前置增强处理方法后,继续调用proceed方法获取到下一个拦截器AspectJAfterAdvice,执行invoke方法
AspectJAfterAdvice
public class AspectJAfterAdvice extends AbstractAspectJAdvice
implements MethodInterceptor, AfterAdvice, Serializable {
public AspectJAfterAdvice(
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
@Override
public boolean isBeforeAdvice() {
return false;
}
@Override
public boolean isAfterAdvice() {
return true;
}
}
可以看到,invoke先调用了proceed方法继续获取下一个拦截器,但是这个时候拦截器链已经遍历完了,那么执行了原方法就返回了,然后递归回退到around增强处理的调用proceed方法的下一步执行,执行完 System.out.println("------@Around: 执行目标方法之后…------");方法后,就走到
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
执行后置增强的逻辑,最后调用链完成,另外两个增强处理的逻辑也类似,有兴趣的可以继续查看在AfterThrowing,AfterReturning增强处理器处是如何串联调用的
JDK动态代理也是通过类似的方式串联调用的,有兴趣的同学可以研究一下,这里不再展开描述
作者: 蔡名炜