浅谈Spring AOP原理

前记

闲来无事写的,貌似距离上一篇都快过去一年了...

环境:spring版本5.1.8

基于注解版

技术不行AND文字不好描述,只看主流程,具体的各位大佬们自己研究研究

1、AopDemo

Demo相信大家都看的懂了。用起来挺简单。需要注意的是切面类要加上@Aspect注解,不然Spring不知道哪个是切面类喲;如果是xml配置版,需要加上<aop:aspectj-autoproxy></aop:aspectj-autoproxy>,如果是注解版,需要在配置类加上@EnableAspectJAutoProxy注解;如果需要使用JoinPoint joinPoint参数,则必须放在第一个位置。

/**
 * 测试类
 */
@Configuration
@EnableAspectJAutoProxy
public class Test {

    @Bean
    public AopService aopService() {
        return new AopService();
    }

    @Bean
    public AopAspect aopAspect() {
        return new AopAspect();
    }

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Test.class);
        AopService aopService = ac.getBean(AopService.class);
        aopService.div(2, 1);
        ac.close();
    }

}

/**
 * AOP类
 */
@Aspect
@Component
public class AopAspect {

    @Pointcut("execution(* com.ricky.blog.AopService.*(..))")
    public void point() {

    }

    @Before("point()")
    public void before(JoinPoint joinPoint) {
        System.out.println("before-" + joinPoint.getSignature().getName());
    }

    @After("point()")
    public void After(JoinPoint joinPoint) {
        System.out.println("After-" + joinPoint.getSignature().getName());
    }

    @AfterReturning("point()")
    public void AfterReturning(JoinPoint joinPoint) {
        System.out.println("AfterReturning-" + joinPoint.getSignature().getName());
    }

    @AfterThrowing("point()")
    public void AfterThrowing(JoinPoint joinPoint) {
        System.out.println("AfterThrowing-" + joinPoint.getSignature().getName());
    }

}

/**
 * 服务类
 */
public class AopService {

    public int div(int num1, int num2) {
        System.out.println(num1 / num2);
        return num1 / num2;
    }

}

运行结果:
before-div
2
After-div
AfterReturning-div



2、个人见解的原理分析

2.1 @EnableAspectJAutoProxy

既然一定要开启@EnableAspectJAutoProxy(Starting from Version 3.1)才能开启AOP功能,那我们就从这个注解入手吧~

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
	/**
	 * 这个貌似是设置实现了接口类是否走cglib,默认不走。
	 */
	boolean proxyTargetClass() default false;
	
	/**
	 * 这个笔者不知道干什么用的,暂时无视。
	 */
	boolean exposeProxy() default false;
}



可以发现EnableAspectJAutoProxy通过@Import(Starting from Version 3.0)导入了AspectJAutoProxyRegistrar(Starting from Version 3.1),看名字应该是自动代理注册器的意思。从版本上来看,只要spring版本在3.1之上就使用注解版的AOP代理了~

2.2 AspectJAutoProxyRegistrar

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		if (enableAspectJAutoProxy != null) {
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}
}



2.2.1 简单分析一下ImportBeanDefinitionRegistrar(Starting from Version 3.1)接口

从代码上可以看到AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,接口中的registerBeanDefinitions方法会传入AnnotationMetadata注解信息以及BeanDefinitionRegistryBean的注册器。

Spring容器会在AbstractApplicationContextrefresh方法中通过调用invokeBeanFactoryPostProcessors(beanFactory)方法,最终调用到实现了ImportBeanDefinitionRegistrar接口的类中重写的方法。这里不过多说明,比较是讲AOP的~其调用链路如下(只有关键步骤,其他shen省略):

AbstractApplicationContext#refresh
AbstractApplicationContext#invokeBeanFactoryPostProcessors
PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors
ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
ConfigurationClassPostProcessor#processConfigBeanDefinitions
ConfigurationClassBeanDefinitionReader#loadBeanDefinitions
ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass
ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsFromRegistrars
ImportBeanDefinitionRegistrar#registerBeanDefinitions


2.2.2 AspectJAutoProxyRegistrar本身逻辑

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
	return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {

	return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

private static BeanDefinition registerOrEscalateApcAsRequired(
		Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

	Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

	if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
		BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
		if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
			int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
			int requiredPriority = findPriorityForClass(cls);
			if (currentPriority < requiredPriority) {
				apcDefinition.setBeanClassName(cls.getName());
			}
		}
		return null;
	}

	RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
	beanDefinition.setSource(source);
	beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
	beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
	registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
	return beanDefinition;
}


可以看到最终调用到了AopConfigUtils#registerOrEscalateApcAsRequired并传递了AnnotationAwareAspectJAutoProxyCreator这么一个类型的参数,并最终吧AnnotationAwareAspectJAutoProxyCreator注册到了Spring容器中。

2.3 AnnotationAwareAspectJAutoProxyCreator

既然向Spring容器中注入了AnnotationAwareAspectJAutoProxyCreator,那就来看看吧~ 首先来张结构体系图:

2.3.1 笔者寻找关键代码的一些经过

从图中可以看出AnnotationAwareAspectJAutoProxyCreator间接地实现了一些接口,其中几个比较重要的接口分别是BeanClassLoaderAwareSmartInstantiationAwareBeanPostProcessorInstantiationAwareBeanPostProcessorBeanPostProcessor

其中BeanClassLoaderAware的作用是获取类加载器,

SmartInstantiationAwareBeanPostProcessor暂不讨论~

InstantiationAwareBeanPostProcessor可以在Bean创建时尝试创建一个新的Bean,在AOP中的实现就是尝试创建一个代理类

BeanPostProcessor的作用就是在bean创建前和创建后做一些操作

经过笔者的一番查找,在AbstractAutoProxyCreator类中发现了两个重要的方法:

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
	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;
		}
	}
.
	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;
}
--------------------分割线--------------------
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
	if (bean != null) {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		if (this.earlyProxyReferences.remove(cacheKey) != bean) {
			return wrapIfNecessary(bean, beanName, cacheKey);
		}
	}
	return bean;
}

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

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

其中postProcessBeforeInstantiationpostProcessAfterInitialization方法中都有Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass());

但是在postProcessBeforeInstantiation方法中,由于TargetSource targetSource = getCustomTargetSource(beanClass, beanName);获取到的TargetSource为空,因为其内部的判断if (this.customTargetSourceCreators != null && this.beanFactory != null && this.beanFactory.containsBean(beanName))customTargetSourceCreators为空,所以并不是在此处创建代理对象,而是在postProcessAfterInitialization中创建的代理对象

2.3.2 创建代理对象过程

直接看代码里面的注释吧...敲字好难敲~

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上面标注的注解信息,如@befor,@After等,并封装成Advisor对象
	//这里面会获得可用的Advisor,并排序,所以才会现有befor,后有after
	//Object[] specificInterceptors本质上是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;
}
--------------------分割线------------------
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);
	}
	// 创建proxy工程
	ProxyFactory proxyFactory = new ProxyFactory();
	proxyFactory.copyFrom(this);

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

	// 绑定Advisor与bean的关系
	Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
	// 给工厂设置一些属性
	proxyFactory.addAdvisors(advisors);
	proxyFactory.setTargetSource(targetSource);
	customizeProxyFactory(proxyFactory);

	proxyFactory.setFrozen(this.freezeProxy);
	if (advisorsPreFiltered()) {
		proxyFactory.setPreFiltered(true);
	}
	// 创建代理
	return proxyFactory.getProxy(getProxyClassLoader());
}
--------------------分割线------------------
public Object getProxy(@Nullable ClassLoader classLoader) {
	// createAopProxy()是选择JDK还是CGLIB
	// 这里我们看CGLIB的getProxy
	return createAopProxy().getProxy(classLoader);
}

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
		Class<?> targetClass = config.getTargetClass();
		if (targetClass == null) {
			throw new AopConfigException("TargetSource cannot determine target class: " +
					"Either an interface or a target is required for proxy creation.");
		}
		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
			return new JdkDynamicAopProxy(config);
		}
		return new ObjenesisCglibAopProxy(config);
	}
	else {
		return new JdkDynamicAopProxy(config);
	}
}

/**
 * 老实说看不懂,反正就是创建一个代理对象了吧~
 */
public Object getProxy(@Nullable ClassLoader classLoader) {
	if (logger.isTraceEnabled()) {
		logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
	}

	try {
		Class<?> rootClass = this.advised.getTargetClass();
		Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

		Class<?> proxySuperClass = rootClass;
		if (ClassUtils.isCglibProxyClass(rootClass)) {
			proxySuperClass = rootClass.getSuperclass();
			Class<?>[] additionalInterfaces = rootClass.getInterfaces();
			for (Class<?> additionalInterface : additionalInterfaces) {
				this.advised.addInterface(additionalInterface);
			}
		}

		// Validate the class, writing log messages as necessary.
		validateClassIfNecessary(proxySuperClass, classLoader);

		// Configure CGLIB Enhancer...
		Enhancer enhancer = createEnhancer();
		if (classLoader != null) {
			enhancer.setClassLoader(classLoader);
			if (classLoader instanceof SmartClassLoader &&
						((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
				enhancer.setUseCache(false);
			}
		}
		enhancer.setSuperclass(proxySuperClass);
		enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
		enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
		enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

		Callback[] callbacks = getCallbacks(rootClass);
		Class<?>[] types = new Class<?>[callbacks.length];
		for (int x = 0; x < types.length; x++) {
			types[x] = callbacks[x].getClass();
		}
		// fixedInterceptorMap only populated at this point, after getCallbacks call above
		enhancer.setCallbackFilter(new ProxyCallbackFilter(
				this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
		enhancer.setCallbackTypes(types);

		// Generate the proxy class and create a proxy instance.
		return createProxyClassAndInstance(enhancer, callbacks);
	}
	catch (CodeGenerationException | IllegalArgumentException ex) {
		throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
				": Common causes of this problem include using a final class or a non-visible class",
				ex);
	}
	catch (Throwable ex) {
		// TargetSource.getTarget() failed
		throw new AopConfigException("Unexpected AOP exception", ex);
	}
}

2.3.3 代理对象如何执行前置、后置等方法

将代理对象保存至容器。执行目标方法时:会调用CglibAopProxy.DynamicAdvisedInterceptor#intercept方法

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
	Object oldProxy = null;
	boolean setProxyContext = false;
	Object target = null;
	TargetSource targetSource = this.advised.getTargetSource();
	try {
		if (this.advised.exposeProxy) {
			oldProxy = AopContext.setCurrentProxy(proxy);
			setProxyContext = true;
		}
		target = targetSource.getTarget();
		Class<?> targetClass = (target != null ? target.getClass() : null);
		// 找到需要执行的Advisor数组
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
		Object retVal;
		if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
			Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
			retVal = methodProxy.invoke(target, argsToUse);
		}
		else {
			//真正调用方法的地方:proceed()方法
			retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
		}
		retVal = processReturnType(proxy, target, method, retVal);
		return retVal;
	}
	finally {
		if (target != null && !targetSource.isStatic()) {
			targetSource.releaseTarget(target);
		}
		if (setProxyContext) {
			AopContext.setCurrentProxy(oldProxy);
		}
	}
}

public Object proceed() throws Throwable {
	//interceptorsAndDynamicMethodMatchers 其实就是Advisor数组,这里是如果当前执行的Advisor已经到了最后一个,就停止递归
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		return invokeJoinpoint();
	}

	Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
	if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
		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 {
			return proceed();
		}
	}
	else {
		// 真正的befor、after等方法。这里在下面截取Demo对应的代码
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
	}
}
-------------分割线-----------
MethodBeforeAdviceInterceptor类的(@Befor):
public Object invoke(MethodInvocation mi) throws Throwable {
	this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
	return mi.proceed();
}

AspectJAfterAdvice类的(@After):
public Object invoke(MethodInvocation mi) throws Throwable {
	try {
		return mi.proceed();
	}
	finally {
		invokeAdviceMethod(getJoinPointMatch(), null, null);
	}
}

AfterReturningAdviceInterceptor类的:(@AfterReturning):
public Object invoke(MethodInvocation mi) throws Throwable {
	Object retVal = mi.proceed();
	this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
	return retVal;
}
从上面的调用关系也可以看出来,是先执行到befor,再after,再本身的方法,再AfterReturning

3 写完了

写的不好,别建议,很多细节没写~不过大致流程就是这样啦~

转载于:https://my.oschina.net/u/3367603/blog/3064405

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值