欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring AOP初始化及执行过程

程序员文章站 2022-03-10 08:37:18
背景当对不同的没有继承关系的对象引入一些公共的行为,比如记录日志,校验安全等,需要编写重复的代码,对一个系统的可维护性来说是非常不友好的,于是,引入了面向切面编程AOP不同于面向对象编程所关注的纵向编程,AOP所关注的是横向编程,为不同的对象方法织入切面切点 Point决定通知作用于哪些连接点通知 Advice决定在连接点做什么,为切面增强提供织入接口通知器 Advisor用于结合Point和AdviceSpring AOP 使用aspectj支持AOP在xml...

背景

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

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

  • 继承关系

    • Spring AOP初始化及执行过程
  • 拦截器分类

    • 如果Advice的实现类没有继承MethodInterceptor需要通过适配器转化为对应的拦截器
    • Spring AOP初始化及执行过程
    • Spring AOP初始化及执行过程
  • 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;
	}

拦截器链执行时序图

Spring AOP初始化及执行过程

本文地址:https://blog.csdn.net/piexie8364/article/details/112251484

相关标签: java spring aop