Spring AOP初始化及执行过程-源码解析

10 篇文章 1 订阅
1 篇文章 0 订阅

背景

  • 当对不同的没有继承关系的对象引入一些公共的行为,比如记录日志,校验安全等,需要编写重复的代码,对一个系统的可维护性来说是非常不友好的,于是,引入了面向切面编程AOP
  • 不同于面向对象编程所关注的纵向编程,AOP所关注的是横向编程,为不同的对象方法织入切面
  • 切点 Point
    • 决定通知作用于哪些连接点
  • 通知 Advice
    • 决定在连接点做什么,为切面增强提供织入接口
  • 通知器 Advisor
    • 用于结合Point和Advice
  • 在这里插入图片描述

Spring AOP 使用aspectj支持AOP

  • 在xml开启AOP功能,并声明AOP Bean
  <aop:aspectj-autoproxy/>
  <bean id="testPrintln" class="com.example.springtest.TestPrintln"></bean>
  <bean class="com.example.springtest.AspectTest"/>
  • 强制使用CGLIB代理
    • <aop:aspectj-autoproxy proxy-target-class=“true”/>
  • 在目标对象内自我调用,实现增强
    • <aop:aspectj-autoproxy expose-proxy=“true”/>
    • (Aservice(AopContext.currentProxy())).b()
  • 注解方式开启
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@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;

}
  • 定义切面 切点Pointcut为* *.test(…)) 匹配的所有连接点的集合
    • @Before(“test()”) 为 增强器
@Aspect
public class AspectTest {
 
  @Pointcut("execution(* *.test(..))")
  public void test() {

  }

  @Before("test()")
  public void before() {
      System.out.println("AspectTest before");
  }

  @Around("test()")
  public Object around(ProceedingJoinPoint proceedingJoinPoint) {
      Object result = null;
      try {
          System.out.println("around before");
          result = proceedingJoinPoint.proceed();
          System.out.println("around after");
      } catch (Throwable throwable) {
          throwable.printStackTrace();
      }
      return result;
  }

  @After("test()")
  public void after() {
      System.out.println("AspectTest after");
  }

  @AfterReturning("test()")
  public void afterReturning() {
      System.out.println("AspectTest afterReturning");
  }

  @AfterThrowing("test()")
  public void afterAfterThrowing() {
      System.out.println("AspectTest afterThrowing");
  }
}

  • 定义要切入的类
public class TestPrintln implements Printlnable{
    @Override
    public void test(){
        System.out.println("我是连接点");
    }
}    
  • 执行结果
around before
before
我是连接点
afterReturning
after
around after

动态AOP自定义标签

  • AopNamespaceHadnler 用于支持AOP标签,最终注册为BeanDefinition,并放入到容器这中
public class AopNamespaceHandler extends NamespaceHandlerSupport {

	/**
	 * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
	 * '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
	 * and '{@code scoped-proxy}' tags.
	 */
	@Override
	public void init() {
		// In 2.0 XSD as well as in 2.1 XSD.
		registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
		// 支持启动spring aop
		registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
		registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

		// Only in 2.0 XSD: moved to context namespace as of 2.1
		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
	}

}

AnnotationAwareAspectJAutoProxyCreator 实现AOP功能

  • 它可以根据@Pointcut注解定义的切点来自动代理匹配的Bean
  • 继承了BeanPostProcessor,执行bean初始化后置处理器 postProcessAfterInitialization方法 返回代理Bean
    • 在父类AbstractAutoProxyCreator中调用postProcessAfterInitialization方法中返回代理Bean
    @Override
      public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
      	if (bean != null) {
      		Object cacheKey = getCacheKey(bean.getClass(), beanName);
      		if (!this.earlyProxyReferences.contains(cacheKey)) {
      			return wrapIfNecessary(bean, beanName, cacheKey);
      		}
      	}
      	return bean;
      }
    
  • 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;
		}
		//如果是基础设施的类 Advice Pointcut 等  或 需要跳过
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		//获取增强器
		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;
	}
  • getAdvicesAndAdvisorsForBean 获取指定Bean的增强器
    @Override
	@Nullable
	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();
	}
  • findEligibleAdvisors 获取指定Bean的增强器
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		//查找所有增强器
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		//获取当前Bean使用的增强器
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			//根据Order排序
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}
  • findCandidateAdvisors 获取所有增强器
    @Override
	protected List<Advisor> findCandidateAdvisors() {
		//查找通过编程方式的增强器.
		List<Advisor> advisors = super.findCandidateAdvisors();
		// Build Advisors for all AspectJ aspects in the bean factory.
		//查找通过注解方式定义的增强器 @Before @Around @After定义的方法
		if (this.aspectJAdvisorsBuilder != null) {
			advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		}
		return advisors;
	}
  • createProxy 创建代理
   /**
	 * Create an AOP proxy for the given bean.
	 * @param beanClass the class of the bean
	 * @param beanName the name of the bean
	 * @param specificInterceptors the set of interceptors that is
	 * specific to this bean (may be empty, but not null)
	 * @param targetSource the TargetSource for the proxy,
	 * already pre-configured to access the bean
	 * @return the AOP proxy for the bean
	 * @see #buildAdvisors
	 */
	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 = new ProxyFactory();
		//根据ProxyConfig获取配置
		proxyFactory.copyFrom(this);

		if (!proxyFactory.isProxyTargetClass()) {
			//判断是否强制使用CGLIB代理
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
			//动态判断使用JDK 还是 CGLIB
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}

		//从容器获取根据interceptorNames配置的增强器
		//对于MethodInterceptor 、AdvisorAdapter支持的Advice 使用DefaultPointcutAdvisor包装
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		//添加增强器
		proxyFactory.addAdvisors(advisors);
		//添加需要代理的目标对象
		proxyFactory.setTargetSource(targetSource);
		//空方法 留给子类覆盖
		customizeProxyFactory(proxyFactory);
		//配置是否可以修改advice
		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}
        //生成代理类
		return proxyFactory.getProxy(getProxyClassLoader());
	}

JdkDynamicAopProxy 实现JDK动态代理

  • 继承InvocationHandler
  • 调用方法 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    • 通过ReflectiveMethodInvocation执行拦截器链
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		MethodInvocation invocation;
		Object oldProxy = null;
		boolean setProxyContext = false;

		TargetSource targetSource = this.advised.targetSource;
		Object target = null;

		try {
			//非从接口继承的 且  方法为 equals
			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;

			//设置了exposeProxy属性 将代理类放入到ThreadLocal
			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.
			// 获取method和targetClass的拦截器(advice)调用链
			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 {
				// 创建拦截器调用链的执行器
				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);
			}
		}
	}
ReflectiveMethodInvocation 执行拦截器链
public Object proceed() throws Throwable {
		//	判断调用链结束是否结束 ,是否已经调用到最后一个
		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 {
			// 继续调用拦截器
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}
拦截器 MethodInterceptor
  • 继承关系

    • 在这里插入图片描述
  • 拦截器分类

    • 如果Advice的实现类没有继承MethodInterceptor需要通过适配器转化为对应的拦截器
    • 在这里插入图片描述
    • 在这里插入图片描述
  • AspectJAroundAdvice

@Override
	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);
	}
  • MethodBeforeAdviceInterceptor
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();
	}
}
  • AspectJAfterAdvice
	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		try {
			return mi.proceed();
		}
		finally {
			invokeAdviceMethod(getJoinPointMatch(), null, null);
		}
	}
  • AspectJAfterThrowingAdvice
@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		try {
			return mi.proceed();
		}
		catch (Throwable ex) {
			if (shouldInvokeOnThrowing(ex)) {
				invokeAdviceMethod(getJoinPointMatch(), null, ex);
			}
			throw ex;
		}
	}
  • AfterReturningAdviceInterceptor
@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		Object retVal = mi.proceed();
		this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
		return retVal;
	}
拦截器链执行时序图

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值