SpringAOP--基与@Aspect注解的aop

本文详细解读了Spring AOP中基于@Aspect注解的AOP应用,涉及切点匹配、前置通知、后置通知和环绕通知的配置,并介绍了如何在配置文件中设置自动代理。重点剖析了AspectJAutoProxyBeanDefinitionParser的工作原理,包括元数据感知Aspect实例工厂、advisor的创建和代理的生成过程。
摘要由CSDN通过智能技术生成

SpringAOP–基与@Aspect注解的aop

demo

@Aspect
public class AspectConfig {

    @Pointcut(value = "execution(* com.poog.code..*.*Test(..)")
    public void test(){}

    @Before(value = "test()")
    public void beforeAdvise(){
        System.out.println("before advise");
    }

    @After(value = "test()")
    public void afterAdivise(){
        System.out.println("after advise");
    }

    @Around(value = "test()")
    public void aroundAdvise(ProceedingJoinPoint joinPoint){
        try {
            System.out.println("around before advise");
            joinPoint.proceed();
            System.out.println("around after advise");
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }
}
public interface TestInterfave {
    public void dosomeTest();
    public void doanotherTest();
    public void a();
    public void b();
}
public class TestImpl implements TestInterfave {
    public void dosomeTest() {
        System.out.println("dosomeTest");
    }

    public void doanotherTest() {
        System.out.println("doanotherTest");
    }

    public void a() {
        System.out.println("a");
    }

    public void b() {
        System.out.println("b");
    }
}

输出结果

around before advise
before advis
dosomeTest
after advise
around after advise
----------------------
around before advise
before advis
doanotherTest
after advise
around after advise

在这个demo中我们需要在配置文件中加入一项配置,代表框架会自动识别并且处理@Aspect注解

<aop:aspectj-autoproxy/>

此标签使用AspectJAutoProxyBeanDefinitionParser来解析

1.注册AnnotationAwareAspectJAutoProxyCreator类,该类负责切面类的解析,代理对象的创建,是AOP的核心类

2.解析 aop:aspectj-autoproxy/ 的两个属性

2.1 expose-proxy:是否暴露当前对象

对于方法内部调用其他方法,如果方法内部的方法也需要增强,则需要将这个属性设置为true,来将内部方法暴露出来

2.2proxy-target-class:默认值为false

当我们需要cglib动态代理时,则将此属性设置为true

加载Aspect切面和Advisor

在上面注册的AnnotationAwareAspectJAutoProxyCreator这个bean最上层是继承了BeanPostProcess,我们知道在IOC创建bean的时候会去调用后处理器来执行一些增强逻辑

1.postProcessBeforeInstantiation

这个方法是在AnnotationAwareAspectJAutoProxyCreator的父类AbstractAutoProxyCreator中被实现的,并且这个方法会在IOC - createBean之前调用,如果这个方法返回一个bean,则创建bean的过程会被短路,不会走正常的逻辑

一般情况是返回NULL,如果用户自定义了一个TargetSource,以用户自定义的逻辑来处理目标实例的话,就会返回处理后的bean

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
   Object cacheKey = getCacheKey(beanClass, beanName);

   if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
      if (this.advisedBeans.containsKey(cacheKey)) {
         return null;
      }
      if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
         this.advisedBeans.put(cacheKey, Boolean.FALSE);
         return null;
      }
   }

   // Create proxy here if we have a custom TargetSource.
   // Suppresses unnecessary default instantiation of the target bean:
   // The TargetSource will handle target instances in a custom fashion.
   TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
   if (targetSource != null) {
      if (StringUtils.hasLength(beanName)) {
         this.targetSourcedBeans.add(beanName);
      }
      Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
      Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
      this.proxyTypes.put(cacheKey, proxy.getClass());
      return proxy;
   }

   return null;
}

2.postProcessAfterInitialization

这个后处理器会在IOC创建AnnotationAwareAspectJAutoProxyCreator这个bean时,做完初始化逻辑后去调用

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
   if (bean != null) {
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
      if (!this.earlyProxyReferences.contains(cacheKey)) {
         return wrapIfNecessary(bean, beanName, cacheKey);
      }
   }
   return bean;
}

这个方法的重点就是wrapIfNecessary

wrapIfNecessary()

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;
   }

   // Create proxy if we have advice.
    //1.
   Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
   if (specificInterceptors != DO_NOT_PROXY) {
      this.advisedBeans.put(cacheKey, Boolean.TRUE);
       //2.
      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.getAdvicesAndAdvisorsForBean

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();
}

1.1findEligibleAdvisors

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    //1.11 获取所有的advisor
   List<Advisor> candidateAdvisors = findCandidateAdvisors();
    //1.12 找到可以用在当前beanName的advisor
   List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
   extendAdvisors(eligibleAdvisors);
   if (!eligibleAdvisors.isEmpty()) {
       //1.13 给advisor排序
      eligibleAdvisors = sortAdvisors(eligibleAdvisors);
   }
   return eligibleAdvisors;
}
1.11 findCandidateAdvisors
xxxxxxxxxx protected List<Advisor> findCandidateAdvisors() {   // Add all the Spring advisors found according to superclass rules.    //调用父类的advisor    //加载的是配置文件中的advisor    //步骤:获取类型为advisor的beanName,然后通过getBean方法获取到bean并加入到集合中   List<Advisor> advisors = super.findCandidateAdvisors();   // Build Advisors for all AspectJ aspects in the bean factory.   if (this.aspectJAdvisorsBuilder != null) {       //获取注解形式的advisor       //步骤:获取工厂里的所有beanName,遍历查找带有@Aspect注解的bean       //在这个bean中获取Advisor,即*1.      advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());   }   return advisors;}

*1.获取advisor

即buildAspectJAdvisors中的List classAdvisors = this.advisorFactory.getAdvisors(factory);

这个方法是个重点

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
   Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
   String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
   validate(aspectClass);

   // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
   // so that it will only instantiate once.
   MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
         new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

   List<Advisor> advisors = new ArrayList<>();
    
    
    //a.
   for (Method method : getAdvisorMethods(aspectClass)) {
       //b.
      Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
      if (advisor != null) {
         advisors.add(advisor);
      }
   }

 ......

   return advisors;
}

a.该方法获取到此AspectClass除Pointcut标记的方法以外的所有方法

private List<Method> getAdvisorMethods(Class<?> aspectClass) {
		final List<Method> methods = new LinkedList<Method>();
		ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {
			@Override
			public void doWith(Method method) throws IllegalArgumentException {
				// Exclude pointcuts
				if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
					methods.add(method);
				}
			}
		});
		Collections.sort(methods, METHOD_COMPARATOR);
		return methods;
	}

b.提取上述方法所对应的advisor

分为两个步骤

1.获取pointcut切点注解信息

2.根据切点注解信息生成advisor

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
			int declarationOrderInAspect, String aspectName) {

		validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

    // 1.
		AspectJExpressionPointcut expressionPointcut = getPointcut(
				candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
		if (expressionPointcut == null) {
			return null;
		}
	//2.
		return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
				this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
	}

1.getPointcut()

private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
		
    
    //这个方法获取到Before、Around、After、 AfterReturning、AfterThrowing、Pointcut的注解信息aspectJAnnotation
    AspectJAnnotation<?> aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		
    	if (aspectJAnnotation == null) {
			return null;
		}

		AspectJExpressionPointcut ajexp =
				new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
    //设置表达式,就是demo中的execution
		ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
    
    //返回生成的ajexp对象,这个对象里面包含了传进来的除pointcut注解以外的方法和匹配表达式,
		return ajexp;
	}

2.return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName)

看一下这个 InstantiationModelAwarePointcutAdvisorImpl 类

该方法前半部分就是将上面的参数赋值一遍,重点在主要逻辑的

instantiateAdvice(this.declaredPointcut);

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
			Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
	this.declaredPointcut = declaredPointcut;
	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;
		this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
	}
}

instantiateAdvice

这个方法从advisor工厂里面拿到一个advise,因为一个advisor是对应一个advise的

private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
		return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut,
				this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
	}

getAdvise

这个方法看着很长,其实逻辑很清楚

主要就是根据aspectJAnnotation的类型创建不同的advisor,因为你传进来的类型可能是@Before,或者@After等等

所有分为了五种逻辑创建:

AspectJMethodBeforeAdvisor,AspectJAfterAdvisor,AspectJAfterRunningAdvisor,AspectJAfterThrowingAdvisor,AspectJAroudAdvisor

@Override
	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;

	switch (aspectJAnnotation.getAnnotationType()) {
		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;
		case AtAround:
			springAdvice = new AspectJAroundAdvice(
					candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
			break;
		case AtPointcut:
			if (logger.isDebugEnabled()) {
				logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
			}
			return null;
		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;
}
1.12 findAdvisorsThatCanApply()

匹配合适beanName的advisor

参数中candidateAdvisors为上一步匹配到的所有advisors

protected List<Advisor> findAdvisorsThatCanApply(
      List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

   ProxyCreationContext.setCurrentProxiedBeanName(beanName);
   try {
      return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
   }
   finally {
      ProxyCreationContext.setCurrentProxiedBeanName(null);
   }
}

然后对advisors进行选择 AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass)

这个方法将advisor分为了两种,IntroductionAdvisor和PointcutAdvisor

IntroductionAdvisor是类级别的增强,和切点无关,主要是为了给类追加更多的方法

这种只需要持有classFilter即可

PointcutAdvisor是方法级别的增强,和切点有关,主要是为了拦截方法

这种需要classFilter和methodMatch,因为PointcutAdvisor内部持有一个pointcut,而pointcut就是由classFilter和methodMatch组成的

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
   if (candidateAdvisors.isEmpty()) {
      return candidateAdvisors;
   }
   List<Advisor> eligibleAdvisors = new ArrayList<>();
   for (Advisor candidate : candidateAdvisors) {
      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;
      }
      if (canApply(candidate, clazz, hasIntroductions)) {
         eligibleAdvisors.add(candidate);
      }
   }
   return eligibleAdvisors;
}

pointcutAdvisor类型的canApply逻辑可分为三步

1.获取advisor中的pointCut

2.获取pointCut中的classFilter,匹配当前targetClass

3.获取pointCut中的methodMatcher,遍历匹配当前targetClass中的所有method

## 2.创建代理creatProxy()



```java
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);
   }

    //1.创建代理工厂
   ProxyFactory proxyFactory = new ProxyFactory();
    //将生产资料放进代理工厂里面
   proxyFactory.copyFrom(this);

   if (!proxyFactory.isProxyTargetClass()) {
      if (shouldProxyTargetClass(beanClass, beanName)) {
         proxyFactory.setProxyTargetClass(true);
      }
      else {
         evaluateProxyInterfaces(beanClass, proxyFactory);
      }
   }

    //2.将interceptor统一适配为advisors
   Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
   proxyFactory.addAdvisors(advisors);
   proxyFactory.setTargetSource(targetSource);
   customizeProxyFactory(proxyFactory);

   proxyFactory.setFrozen(this.freezeProxy);
   if (advisorsPreFiltered()) {
      proxyFactory.setPreFiltered(true);
   }

    //3.获取代理,这个逻辑看另一个aop笔记
   return proxyFactory.getProxy(getProxyClassLoader());
}

2.2将interceptor统一适配为advisors

protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
   // Handle prototypes correctly...
   Advisor[] commonInterceptors = resolveInterceptorNames();

   List<Object> allInterceptors = new ArrayList<>();
   if (specificInterceptors != null) {
      allInterceptors.addAll(Arrays.asList(specificInterceptors));
      if (commonInterceptors.length > 0) {
         if (this.applyCommonInterceptorsFirst) {
            allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
         }
         else {
            allInterceptors.addAll(Arrays.asList(commonInterceptors));
         }
      }
   }
   if (logger.isDebugEnabled()) {
      int nrOfCommonInterceptors = commonInterceptors.length;
      int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
      logger.debug("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
            " common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
   }

   Advisor[] advisors = new Advisor[allInterceptors.size()];
   for (int i = 0; i < allInterceptors.size(); i++) {
       //适配方法
      advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
   }
   return advisors;
}

适配方法,将各种interceptor也就是advise适配为advisor

将传进来的增强器分为三类

1.advisor类,直接返回

2.advise类型,包装为DefaultPointcutAdvisor类

advise又分为两种:MethodInterceptor和其他例如MethodBeforeAdvice,AfterReturningAdvice,ThrowsAdvice



```java
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
   if (adviceObject instanceof Advisor) {
      return (Advisor) adviceObject;
   }
   if (!(adviceObject instanceof Advice)) {
      throw new UnknownAdviceTypeException(adviceObject);
   }
   Advice advice = (Advice) adviceObject;
   if (advice instanceof MethodInterceptor) {
      // So well-known it doesn't even need an adapter.
      return new DefaultPointcutAdvisor(advice);
   }
   for (AdvisorAdapter adapter : this.adapters) {
      // Check that it is supported.
      if (adapter.supportsAdvice(advice)) {
         return new DefaultPointcutAdvisor(advice);
      }
   }
   throw new UnknownAdviceTypeException(advice);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值