Spring基于@Aspect注解实现AOP的源码解析


前言

AOP面向切面编程,用于为一批目标方法(JoinPoint)配置增强方法(Advice)来实现切面。Advice通过PointCut(一个表达式)匹配目标方法(JoinPoint)。应用层面可以通过配置文件和注解两种方式创建Advice和PointCut。这次只分析@Aspect注解方式。


一、AOP的应用Demo

下面是在SpringBoot项目中,基于注解对AOP的使用

maven依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-aop</artifactId>
 </dependency>

application.yml配置文件

spring:
  aop:
    proxy-target-class: false

动态代理JDK的比较熟悉,将默认的CGLIB改为JDK。方便后续源码分析说明

目标方法类

package com.example.demo.service.impl;
@Service
public class JoinPointService implements JoinPointServiceI {
	//这个方法就是一个JoinPoint
    @Override
    public void doSome1(String a) {
        System.out.println("JoinPoint-doSome1:"+ "["+a+"]");
    }
}

增强方法和切入点

@Aspect
@Component
public class PointCutHandle {
	//这里就是PointCut 用于与目标方法匹配
    @Pointcut("execution(public * com.example.demo.service.impl.*.*(..))")
    public void pointcut(){}

	//前置增强方法 Advice
    @Before("pointcut()")
    public void before(JoinPoint joinPoint) {
        System.out.println("before : " + Arrays.toString(joinPoint.getArgs()));
    }
	
	//后置增强方法 Advice
    @AfterReturning("pointcut()")
    public void afterReturning(JoinPoint joinPoint) {
        System.out.println("afterReturning : " + Arrays.toString(joinPoint.getArgs()));
    }

	//最终后置增强方法 Advice
    @After("pointcut()")
    public void after(JoinPoint joinPoint) {
        System.out.println("after : " + Arrays.toString(joinPoint.getArgs()));
    }
}

常用的有5种Advice,这里列出了3种

测试类

@SpringBootTest
class DemoApplicationTests {

    @Autowired
    private JoinPointServiceI joinPointService;

    @Test
    void contextLoads() {
        joinPointService.doSome1("9981");
    }

}

最终执行结果
在这里插入图片描述

before : [9981]
JoinPoint-doSome1:[9981]
afterReturning : [9981]
after : [9981]

Demo中我通过注解的方式定义了3个增强方法和一个切入点。因为切入点和目标方法匹配所以目标方法执行时,3个增强方法也有序执行了。这个过程Spring源码是如何实现的呢?

二、源码分析

源码分析前先列出需要分析的主要步骤

  • 通过自动装配,注入一个后处理器bean(AnnotationAwareAspectJAutoProxyCreator)。
  • 后处理器bean对符合要求的bean进行动态代理。
  • 被代理的bean方法调用。

下面基于这个流程跟下源码

2.1 注入AnnotationAwareAspectJAutoProxyCreator

SpringBoot通过自动装配类AopAutoConfiguration完成AnnotationAwareAspectJAutoProxyCreator的注册。先看下AopAutoConfiguration

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {
@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(Advice.class)
	static class AspectJAutoProxyingConfiguration {
		//jdk分支
		//会走这个分支 因为配置文件里我设置了proxy-target-class=false
		@Configuration(proxyBeanMethods = false)
		//重点看这个注解。与cglib分支的区别就是proxyTargetClass=false
		@EnableAspectJAutoProxy(proxyTargetClass = false)
		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",
				matchIfMissing = false)
		static class JdkDynamicAutoProxyConfiguration {

		}
		
		//cglib分支
		@Configuration(proxyBeanMethods = false)
		@EnableAspectJAutoProxy(proxyTargetClass = true)
		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
				matchIfMissing = true)
		static class CglibAutoProxyConfiguration {

		}
	}
	...}

接着跟下@EnableAspectJAutoProxy

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//跟这个注册器 既然是注册了一个bean,那肯定要跟注册器了
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
	/**
	 * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
	 * to standard Java interface-based proxies. The default is {@code false}.
	 */
	boolean proxyTargetClass() default false;

	/**
	 * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
	 * for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
	 * Off by default, i.e. no guarantees that {@code AopContext} access will work.
	 * @since 4.3.1
	 */
	boolean exposeProxy() default false;
}

接着跟@AspectJAutoProxyRegistrar

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		//继续跟这里 注册AnnotationAwareAspectJAutoProxyCreator
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		
		//这个分支这次不跟进了		
		if (enableAspectJAutoProxy != null) {
			//设置AnnotationAwareAspectJAutoProxyCreator中的proxyTargetClass
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				//强制使用cglib代理
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			//设置代理对象是否可以暴漏
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}
}

接着跟AopConfigUtils类,最终将AnnotationAwareAspectJAutoProxyCreator注册到工厂

public abstract class AopConfigUtils {
	//入口方法
	public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
		//继续跟这里
        return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, (Object)null);
    }
	//这里将AnnotationAwareAspectJAutoProxyCreator注册到工厂
	public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {
        return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
    }
}

可以看到AnnotationAwareAspectJAutoProxyCreator本质是一个BeanPostProcessor
在这里插入图片描述

2.2 后处理器Bean对符合要求的bean进行动态代理

处理方法使用了BeanPostProcessor的postProcessAfterInitialization方法。该方法由AnnotationAwareAspectJAutoProxyCreator的太爷爷AbstractAutoProxyCreator类实现。下面跟下这个方法

//入口方法 对bean执行初始化后处理
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
       if (bean != null) {
           Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
           if (this.earlyProxyReferences.remove(cacheKey) != bean) {
           	   //重点跟这里
               return this.wrapIfNecessary(bean, beanName, cacheKey);
           }
       }

       return bean;
}
// AOP实现的核心方法
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	...// 构建Advisor集合
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
	if (specificInterceptors != DO_NOT_PROXY) {
		this.advisedBeans.put(cacheKey, Boolean.TRUE);
		//创建代理对象
		Object proxy = createProxy(
				bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
		this.proxyTypes.put(cacheKey, proxy.getClass());
		return proxy;
	}

	this.advisedBeans.put(cacheKey, Boolean.FALSE);
	return bean;
}

这个方法主要包含两个部分。

  • 获取与被处理bean匹配的Advisor集合
  • 对Advisor集合非空的bean创建代理类

这里先回答两个问题

  1. 为什么说specificInterceptors是Advisor集合,本次只对@Aspect注解实现AOP的源码进行分析,在这种情况下getAdvicesAndAdvisorsForBean()方法返回的都是Advisor对象。
  2. 为什么对Advisor集合非空的bean创建代理对象呢?这里先简单介绍下Advisor对象。该对象包含一个增强方法(Advice)和一个PointCut(用于和目标bean的方法匹配)。也就是说如果Advisor集合非空就说明bean有方法需要被增强,所以这个bean需要被代理。

接下来基于这两部分继续分析

2.2.1 获取与被处理bean匹配的Advisor集合

跟进getAdvicesAndAdvisorsForBean方法,该方法由子类AbstractAdvisorAutoProxyCreator实现

//入口方法
protected Object[] getAdvicesAndAdvisorsForBean(
			Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
		//跟这里
		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		return advisors.toArray();
	}
//核心方法
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		//获取所有Advisor对象集合
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		//获取与当前bean匹配的Advisor对象集合
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}

到这里又出现了两个分支,首先获取所有Advisor对象集合,然后获取与当前bean匹配的Advisor对象集合。下面依次跟进

2.2.1.1 获取所有Advisor对象集合

跟进findCandidateAdvisors方法,该方法由AnnotationAwareAspectJAutoProxyCreator类实现

protected List<Advisor> findCandidateAdvisors() {
		//原始构建Advisor的方式 这次不看这个分支了
		List<Advisor> advisors = super.findCandidateAdvisors();
		// Build Advisors for all AspectJ aspects in the bean factory.
		if (this.aspectJAdvisorsBuilder != null) {
			//重点看这个分支 基于@Aspect注解构建Advisor对象
			advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		}
		return advisors;
	}

跟进buildAspectJAdvisors方法,该方法由BeanFactoryAspectJAdvisorsBuilder类实现。该方法主要作用是将所有被@Aspect注释的bean转化为一个Advisor对象集合。主要步骤如下

  • 获取所有bean名称
  • 挑选出被@Aspect注释的bean名称
  • 基于bean名称构建元数据工厂(MetadataAwareAspectInstanceFactory),该工厂可以创建@Aspect注释的bean
  • 最后使用全局变量advisorFactory,将MetadataAwareAspectInstanceFactory构建成一组Advisor对象
public List<Advisor> buildAspectJAdvisors() {
		List<String> aspectNames = this.aspectBeanNames;
		//首次构建Advisor
		if (aspectNames == null) {
			synchronized (this) {
				aspectNames = this.aspectBeanNames;
				if (aspectNames == null) {
					List<Advisor> advisors = new ArrayList<>();
					aspectNames = new ArrayList<>();
					//获取所有bean名称	
					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);
						
					for (String beanName : beanNames) {
						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注释的bean名称
						if (this.advisorFactory.isAspect(beanType)) {
							aspectNames.add(beanName);
							AspectMetadata amd = new AspectMetadata(beanType, beanName);
							if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
								//构建元数据工厂,该工厂可以获取被@Aspect注释的bean对象
								MetadataAwareAspectInstanceFactory factory =
										new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
								//核心方法:使用advisorFactory对象的getAdvisors方法构建Advisor	
								List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
								//进行缓存
								if (this.beanFactory.isSingleton(beanName)) {
									this.advisorsCache.put(beanName, classAdvisors);
								}
								else {
									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;
				}
			}
		}
		//非首次基于缓存构建Advisor
		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;
	}

继续跟进this.advisorFactory.getAdvisors()方法,目的是将MetadataAwareAspectInstanceFactory变成一组Advisor对象。其中全局变量this.advisorFactory是ReflectiveAspectJAdvisorFactory类型的。该全局变量在BeanFactoryAspectJAdvisorsBuilder的构造器中创建。这个工厂主要用来构建AOP所需要的核心对象Advisor、Pointcut、Advice。主要流程如下

  • 获取@Aspect注释的bean的所有非@Pointcut注释的方法
  • 如果方法被这5种(@Around,@Before.class,@After, @AfterReturning,@AfterThrowing)注解中的任意一个注释,为其创建Pointcut对象
  • 如果Pointcut对象非空,构建Advisor对象。其构造函数中包含Pointcut对象,并且其构造函数中会创建Advice对象

接着跟下这个方法

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
	Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
	String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
	validate(aspectClass);
	//对元数据工厂进一步封装,目的是保证获取的bean是单例模式。这里不重点关注了
	MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
			new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

	List<Advisor> advisors = new ArrayList<>();
	//获取bean中所有非@Pointcut注释的方法
	for (Method method : getAdvisorMethods(aspectClass)) {
		//核心方法 构建Advisor对象 跟进这里
		Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
		if (advisor != null) {
			advisors.add(advisor);
		}
	}

	// 该分支 本次不关注
	if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
		Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
		advisors.add(0, instantiationAdvisor);
	}

	// 该分支 本次不关注
	for (Field field : aspectClass.getDeclaredFields()) {
		Advisor advisor = getDeclareParentsAdvisor(field);
		if (advisor != null) {
			advisors.add(advisor);
		}
	}

	return advisors;
}

//创建Advisor对象
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
			int declarationOrderInAspect, String aspectName) {

	validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
	//为被(Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class)注释的方法创建Pointcut对象
	AspectJExpressionPointcut expressionPointcut = getPointcut(
			candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
	if (expressionPointcut == null) {
		return null;
	}
	//创建Advisor对象 看看这个构造方法,将自己也传入的目的是为了后续构建Advice
	return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
			this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

跟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;
	//构建AOP核心对象的工厂
	this.aspectJAdvisorFactory = aspectJAdvisorFactory;
	//构建元数据bean的工厂
	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;
		//Advice的创建 跟这里
		this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
	}
}
//创建Adivce对象
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
	//可以看到Advice也是由ReflectiveAspectJAdvisorFactory创建的
	Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
			this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
	return (advice != null ? advice : EMPTY_ADVICE);
}

跟进ReflectiveAspectJAdvisorFactory的getAdvice方法

public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

	Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
	validate(candidateAspectClass);

	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;
	//5种Advice的创建。可以看出Advice封装了一个只差入参就能被调用的增强方法。通过反射调用一个方法需要3个基本元素,入参、方法对象、实体类。其构造方法中包含了方法对象和元素据工厂(可以随时创建实体类)。
	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;
}
2.2.1.2 获取与被处理bean匹配的Advisor对象集合

回到AbstractAdvisorAutoProxyCreator类的findEligibleAdvisors方法。

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
	//candidateAdvisors对象已经初始化完毕。其内部的类型是InstantiationModelAwarePointcutAdvisorImpl
	List<Advisor> candidateAdvisors = findCandidateAdvisors();
	//接着跟这个方法
	List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
	extendAdvisors(eligibleAdvisors);
	if (!eligibleAdvisors.isEmpty()) {
		eligibleAdvisors = sortAdvisors(eligibleAdvisors);
	}
	return eligibleAdvisors;
}

//匹配方法
protected List<Advisor> findAdvisorsThatCanApply(
			List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

	ProxyCreationContext.setCurrentProxiedBeanName(beanName);
	try {
		//最终的匹配任务委托给了AopUtils类
		return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
	}
	finally {
		ProxyCreationContext.setCurrentProxiedBeanName(null);
	}
}

现在所有被@Aspect注释的bean已经被转化成了InstantiationModelAwarePointcutAdvisorImpl对象,封装在candidateAdvisors中。InstantiationModelAwarePointcutAdvisorImpl本质上是PointcutAdvisor类型的而不是IntroductionAdvisor类型的,所以后续IntroductionAdvisor类型的处理不跟进了。该方法主要流程是便利所有Advisor,用Advisor的切入点表达式与被处理bean以及该bean的所有父辈的所有方法进行匹配,只要匹配一条就将Advisor加入目标集合。接着跟进AopUtils的findAdvisorsThatCanApply方法。

//入口方法
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
		if (candidateAdvisors.isEmpty()) {
			return candidateAdvisors;
		}
		List<Advisor> eligibleAdvisors = new ArrayList<>();
		for (Advisor candidate : candidateAdvisors) {
			//IntroductionAdvisor相关的分支不关注了
			if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
				//匹配成功放入结果集
				eligibleAdvisors.add(candidate);
			}
		}
		
		boolean hasIntroductions = !eligibleAdvisors.isEmpty();
		for (Advisor candidate : candidateAdvisors) {
			if (candidate instanceof IntroductionAdvisor) {
				// already processed
				continue;
			}
			//跟进canApply方法1
			if (canApply(candidate, clazz, hasIntroductions)) {
				eligibleAdvisors.add(candidate);
			}
		}
		return eligibleAdvisors;
}

//canApply方法1
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
		//IntroductionAdvisor的分支 不关注了
		if (advisor instanceof IntroductionAdvisor) {
			return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
		}
		//重点看这里
		else if (advisor instanceof PointcutAdvisor) {
			PointcutAdvisor pca = (PointcutAdvisor) advisor;
			//跟进canApply方法2
			return canApply(pca.getPointcut(), targetClass, hasIntroductions);
		}
		else {
			// It doesn't have a pointcut so we assume it applies.
			return true;
		}
	}
//canApply方法2
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
	//pc的类型是AspectJExpressionPointcut本质上是IntroductionAwareMethodMatcher 

	Assert.notNull(pc, "Pointcut must not be null");
	if (!pc.getClassFilter().matches(targetClass)) {
		return false;
	}
	//AspectJExpressionPointcut类型的pc,pc.getMethodMatcher会返回pc自己
	MethodMatcher methodMatcher = pc.getMethodMatcher();
	if (methodMatcher == MethodMatcher.TRUE) {
		// No need to iterate the methods if we're matching any method anyway...
		return true;
	}
	//这里会执行强转
	IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
	if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
		introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
	}
	//将被处理的bean以及其所有父辈放入classes集合中
	Set<Class<?>> classes = new LinkedHashSet<>();
	if (!Proxy.isProxyClass(targetClass)) {
		classes.add(ClassUtils.getUserClass(targetClass));
	}
	classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
	//依次便利bean以及其父辈
	for (Class<?> clazz : classes) {
		Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
		//便利每个类的所有方法
		for (Method method : methods) {
			//这里会走introductionAwareMethodMatcher.matche方法完成方法级别的匹配
			//任何一个方法匹配 都返回true
			if (introductionAwareMethodMatcher != null ?
					introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
					methodMatcher.matches(method, targetClass)) {
				return true;
			}
		}
	}

	return false;
}

2.2.2 创建代理对象

回到AbstractAutoProxyCreator的wrapIfNecessary方法。后续流程主要是将被处理bean的封装类和与被处理bean相关的Advior以及采用哪种方法代理(proxyTargetClass)统一委托给ProxyFactory完成代理对象的创建。

//入口方法
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		//目前与被处理bean匹配的Advior对象已被封装到specificInterceptors对象中
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			//将被处理bean的封装类和与被处理bean相关的Advior交给方法1进行代理对象的创建,跟进方法1
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

//方法1
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();
		//这里将proxyTargetClass的值赋予了proxyFactory,用于确定使用jdk还是cglib
		//proxyTargetClass的值最早来至@EnableAspectJAutoProxy(proxyTargetClass = false)注解
		proxyFactory.copyFrom(this);

		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}
		//将specificInterceptors统一转化为Advisor
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		//将advisors交给委托对象
		proxyFactory.addAdvisors(advisors);
		//将被处理bean的封装类交给委托对象
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}
		//执行动态代理
		return proxyFactory.getProxy(getProxyClassLoader());
	}

继续跟进ProxyFactory的getProxy方法

public Object getProxy(@Nullable ClassLoader classLoader) {
  	//createAopProxy()不具体跟了,该方法主要做了两件事
  	//1--创建代理工厂(只有JdkDynamicAopProxy和ObjenesisCglibAopProxy两种),重点看JdkDynamicAopProxy
  	//2--将携带Advisor集合和被处理bean封装类的ProxyFactory传给JdkDynamicAopProxy的advised属性
	return createAopProxy().getProxy(classLoader);
}

继续跟进JdkDynamicAopProxy的getProxy方法

public Object getProxy(@Nullable ClassLoader classLoader) {
	if (logger.isTraceEnabled()) {
		logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
	}
	//拿到被处理bean的所有接口
	Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
	findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
	//创建动态代理,最有一个参数是this。也就是说JdkDynamicAopProxy是一个InvocationHandler
	return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

2.4 代理对象方法调用

基于上边的分析,JdkDynamicAopProxy本质上是一个InvocationHandler。所以代理方法的执行就是他的invoke方法。该方法主要做两件事

  • 使用advised构建出一个有序的方法链
  • 委托ReflectiveMethodInvocation执行方法链
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 {
		//基类Object的方法不做代理
		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);

		// 重点1 使用advised构建出一个有序的方法链
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

		//如果方法链是空的直接执行目标方法
		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 {
			MethodInvocation invocation =
					new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
			//重点2 委托ReflectiveMethodInvocation执行方法链
			retVal = invocation.proceed();
		}

		// 这个分支不重点看了
		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);
		}
	}
}

2.4.1 方法链的创建

跟进getInterceptorsAndDynamicInterceptionAdvice方法

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
	MethodCacheKey cacheKey = new MethodCacheKey(method);
	List<Object> cached = this.methodCache.get(cacheKey);
	if (cached == null) {
		//其中全局变量this.advisorChainFactory是DefaultAdvisorChainFactory类型
		cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
				this, method, targetClass);
		this.methodCache.put(cacheKey, cached);
	}
	return cached;
}

跟进DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法。该方法从与被代理bean相关的Advisor中挑出与当前方法相关的Advisor,然后将拿到Advisor中的Advice并将其转化成MethodInterceptor类型,最终构建出一个MethodInterceptor数组即我们的方法链。

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
			Advised config, Method method, @Nullable Class<?> targetClass) {

	// This is somewhat tricky... We have to process introductions first,
	// but we need to preserve order in the ultimate list.
	AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
	Advisor[] advisors = config.getAdvisors();
	//封装最终的方法链
	List<Object> interceptorList = new ArrayList<>(advisors.length);
	Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
	Boolean hasIntroductions = null;

	for (Advisor advisor : advisors) {
		//跟这个分支 因为我们的advisor就是PointcutAdvisor类型的
		if (advisor instanceof PointcutAdvisor) {
			//获取切入点,从与当前类匹配的Advisor中找出与当前方法匹配的Advisor
			PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
			if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
				MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
				boolean match;
				if (mm instanceof IntroductionAwareMethodMatcher) {
					if (hasIntroductions == null) {
						hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
					}
					match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
				}
				else {
					match = mm.matches(method, actualClass);
				}
				if (match) {
					//如果匹配将advisor转化为MethodInterceptor对象,便于后续方法链的执行
					MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
					if (mm.isRuntime()) {
						// Creating a new object instance in the getInterceptors() method
						// isn't a problem as we normally cache created chains.
						for (MethodInterceptor interceptor : interceptors) {
							interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
						}
					}
					else {
						interceptorList.addAll(Arrays.asList(interceptors));
					}
				}
			}
		}
		//这个分支不跟进了
		else if (advisor instanceof IntroductionAdvisor) {
			IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
			if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
				Interceptor[] interceptors = registry.getInterceptors(advisor);
				interceptorList.addAll(Arrays.asList(interceptors));
			}
		}
		//这个分支不跟进了
		else {
			Interceptor[] interceptors = registry.getInterceptors(advisor);
			interceptorList.addAll(Arrays.asList(interceptors));
		}
	}

	return interceptorList;
}

这里有个问题,为什么要将Advice转化成MethodInterceptor类型呢?目的是将5中Advice对象统一适配成一种类型,这样在后续方法链的执行中可以抽公共方法。
下边是五种Advice转化成MethodInterceptor的情况

  • AspectJAroundAdvice、AspectJAfterAdvice、AspectJAfterThrowingAdvice本身就是MethodInterceptor。直接强转
  • AspectJMethodBeforeAdvice不是MethodInterceptor类型,通过适配器适配成MethodBeforeAdviceInterceptor
  • AspectJAfterReturningAdvice不是MethodInterceptor类型,通过适配器适配成AfterReturningAdviceInterceptor

2.4.2 方法链的执行

方法链的执行跟ReflectiveMethodInvocation的proceed方法。

public Object proceed() throws Throwable {
	//全局变量this.interceptorsAndDynamicMethodMatchers就是方法链
	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();
		}
	}
	//正常分支 执行MethodInterceptor的invoke方法。这里主要就是增强方法的执行
	else {
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
	}
}

在方法链的创建中分析出MethodInterceptor有5中类型(AspectJAroundAdvice、AspectJAfterAdvice、AspectJAfterThrowingAdvice、MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor)接下来依次看下其invoke方法

2.4.2.1 方法链的执行MethodBeforeAdviceInterceptor的invoke
public Object invoke(MethodInvocation mi) throws Throwable {
	//这里的advice就是AspectJMethodBeforeAdvice
	this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
	return mi.proceed();
}

这里可以看到先执行增强方法,然后继续执行方法链。这里保证了AspectJMethodBeforeAdvice增强方法的先执行。
跟进AspectJMethodBeforeAdvice的before方法。看看如何通过反射执行的增强方法

public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
		//该方法由其父类AbstractAspectJAdvice统一实现
		invokeAdviceMethod(getJoinPointMatch(), null, null);
}

跟进AbstractAspectJAdvice的invokeAdviceMethod方法

protected Object invokeAdviceMethod(
		@Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex)
		throws Throwable {
	//跟进方法1
	return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
}
//方法1
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
		Object[] actualArgs = args;
		if (this.aspectJAdviceMethod.getParameterCount() == 0) {
			actualArgs = null;
		}
		try {
			ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
			//通过反射完成增强方法的调用
			//aspectJAdviceMethod就是之前封装的增强方法对象
			//this.aspectInstanceFactory内部封装了被@Aspect注释的bean,在这里创建了bean实例
			//最后的参数时这次方法调用传的
			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();
		}
	}
2.4.2.2 方法链的执行AfterReturningAdviceInterceptor的invoke
public Object invoke(MethodInvocation mi) throws Throwable {
	Object retVal = mi.proceed();
	//这里的this.advice就是AspectJAfterReturningAdvice对象
	this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
	return retVal;
}

可以看到先执行方法链中的其他方法,最后执行增强方法。保证了增强方法的后执行
跟进this.advice.afterReturning方法,看看如何通过反射执行的增强方法

public void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable {
	if (shouldInvokeOnReturnValueOf(method, returnValue)) {
		//和AspectJMethodBeforeAdvice一样逻辑 不继续跟进了
		invokeAdviceMethod(getJoinPointMatch(), returnValue, null);
	}
}
2.4.2.3 方法链的执行AspectJAfterAdvice的invoke
public Object invoke(MethodInvocation mi) throws Throwable {
	try {
		return mi.proceed();
	}
	finally {
	    //增强方法执行
		invokeAdviceMethod(getJoinPointMatch(), null, null);
	}
}

将增强方法放到finally中保证最终执行

2.4.2.4 方法链的执行AspectJAfterThrowingAdvice的invoke
public Object invoke(MethodInvocation mi) throws Throwable {
	try {
		return mi.proceed();
	}
	catch (Throwable ex) {
		if (shouldInvokeOnThrowing(ex)) {
			//增强方法
			invokeAdviceMethod(getJoinPointMatch(), null, ex);
		}
		throw ex;
	}
}

将增强方法放到catch语句块中,保证异常时执行

2.4.2.5 方法链的执行AspectJAroundAdvice的invoke
public Object invoke(MethodInvocation mi) throws Throwable {
		if (!(mi instanceof ProxyMethodInvocation)) {
			throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
		}
		ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
		ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
		JoinPointMatch jpm = getJoinPointMatch(pmi);
		return invokeAdviceMethod(pjp, jpm, null, null);
	}

最特殊的Advice,其将方法链封装到了ProceedingJoinPoint对象中并传给了增强方法。增强方法中可以通过控制方法链的调用时机达到和其他四种的Advice任意一个一样的效果。甚至可以达到其他4种的任意组合效果。相当于自定义MethodInvocation的invoke方法了


总结

这里在总结下总体流程

  • 创建代理对象
  • 1 自动装配注入AnnotationAwareAspectJAutoProxyCreator后置处理器
  • 2 后置处理器将所有@Aspect注释的bean转化为一个Advisor集合
  • 3 为匹配了Advisor的被处理bean创建代理对象
  • 执行代理对象方法
  • 1 创建方法执行链,将与当前方法匹配的Advisor集合转化为MethodInterceptor集合
  • 2 执行方法链,依次执行MethodInterceptor的invoke方法。其方法内部保证了不同Advice的执行顺序
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring AOPSpring框架中的一个重要模块,它提供了面向切面编程(AOP)的支持。AOP是一种编程思想,它可以在不改变原有代码的情况下,通过在程序运行时动态地将代码“织入”到现有代码中,从而实现对原有代码的增强。 Spring AOP提供了基于注解AOP实现,使得开发者可以通过注解的方式来定义切面、切点和通知等相关内容,从而简化了AOP的使用。 下面是一个基于注解AOP实现的例子: 1. 定义切面类 ```java @Aspect @Component public class LogAspect { @Pointcut("@annotation(Log)") public void logPointcut() {} @Before("logPointcut()") public void beforeLog(JoinPoint joinPoint) { // 前置通知 System.out.println("执行方法:" + joinPoint.getSignature().getName()); } @AfterReturning("logPointcut()") public void afterLog(JoinPoint joinPoint) { // 后置通知 System.out.println("方法执行完成:" + joinPoint.getSignature().getName()); } @AfterThrowing(pointcut = "logPointcut()", throwing = "ex") public void afterThrowingLog(JoinPoint joinPoint, Exception ex) { // 异常通知 System.out.println("方法执行异常:" + joinPoint.getSignature().getName() + ",异常信息:" + ex.getMessage()); } } ``` 2. 定义业务逻辑类 ```java @Service public class UserService { @Log public void addUser(User user) { // 添加用户 System.out.println("添加用户:" + user.getName()); } @Log public void deleteUser(String userId) { // 删除用户 System.out.println("删除用户:" + userId); throw new RuntimeException("删除用户异常"); } } ``` 3. 在配置文件中开启AOP ```xml <aop:aspectj-autoproxy/> <context:component-scan base-package="com.example"/> ``` 在这个例子中,我们定义了一个切面类LogAspect,其中通过@Aspect注解定义了一个切面,通过@Pointcut注解定义了一个切点,通过@Before、@AfterReturning和@AfterThrowing注解分别定义了前置通知、后置通知和异常通知。 在业务逻辑类中,我们通过@Log注解标注了需要增强的方法。 最后,在配置文件中,我们通过<aop:aspectj-autoproxy/>开启了AOP功能,并通过<context:component-scan>扫描了指定包下的所有组件。 这样,当我们调用UserService中的方法时,就会触发LogAspect中定义的通知,从而实现对原有代码的增强。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值