spring系列四之springaop源码解析

对springaop解析主要针对XML配置和注解两部分进行讲解:
1、首先对XML配置的方式进行讲解,在讲解spring容器初始化的章节中,其中有一部分是讲解解析<beans>元素的

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
	if (delegate.isDefaultNamespace(root)) {
		NodeList nl = root.getChildNodes();
		// 遍历<beans>
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (node instanceof Element) {
				Element ele = (Element) node;
				if (delegate.isDefaultNamespace(ele)) {
					// 解析<bean>转换成beanDefinition
					parseDefaultElement(ele, delegate);
				}
				else {
					// 解析自定义标签的元素(aop的配置)
					delegate.parseCustomElement(ele);
				}
			}
		}
	}
	else {
		delegate.parseCustomElement(root);
	}
}

delegate.parseCustomElement(ele)这个函数就是对自定义标签的解析(包括aop标签)

// BeanDefinitionParserDelegate:BeanDefinition的解析器
public BeanDefinition parseCustomElement(Element ele) {
	return parseCustomElement(ele, null);
}


public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
	String namespaceUri = getNamespaceURI(ele);
	if (namespaceUri == null) {
		return null;
	}
	// 核心代码:根据命名空间Uri获取命名空间处理器
	NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
	if (handler == null) {
		error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
		return null;
	}
	return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

如果解析的是Aop标签,那么对应的处理器是AopNamespaceHandler,看一下这个处理器的代码实现:

// 注册相关的解析器
public void init() {
	// In 2.0 XSD as well as in 2.1 XSD.
	registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
	// 注册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());
}
// 找出符合条件的BeanDefinition解析器并解析(AspectJAutoProxyBeanDefinitionParser)
public BeanDefinition parse(Element element, ParserContext parserContext) {
	BeanDefinitionParser parser = findParserForElement(element, parserContext);
	return (parser != null ? parser.parse(element, parserContext) : null);
}
// AspectJAutoProxyBeanDefinitionParser对应的实现
public BeanDefinition parse(Element element, ParserContext parserContext) {
	AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
	extendBeanDefinition(element, parserContext);
	return null;
}

// 继续进入AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element)
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			ParserContext parserContext, Element sourceElement) {
	// 注册AnnotationAwareAspectJAutoProxyCreator到容器
	BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));
	
	// 对proxy-target-class以及expose-proxy属性的处理
	// proxy-target-class: true是使用cglib代理,false是使用jdk代理,默认使用false
	// expose-proxy: false(默认不暴露代理),true(暴露代理)
	useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
	// 注册组件并通知,以便监听器做进一步处理
	registerComponentIfNecessary(beanDefinition, parserContext);
}

以上完成了XML方式注册AnnotationAwareAspectJAutoProxyCreator到容器的流程
2、下面讲解一下以注解的方式注册AnnotationAwareAspectJAutoProxyCreator
看一下注册入口:

@Configuration(
	 proxyBeanMethods = false
	)
@ConditionalOnProperty(
 prefix = "spring.aop",
 name = {"auto"},
 havingValue = "true",
 matchIfMissing = true
)
public class AopAutoConfiguration {
 public AopAutoConfiguration() {
 }

 @Configuration(
     proxyBeanMethods = false
 )
 @ConditionalOnMissingClass({"org.aspectj.weaver.Advice"})
 @ConditionalOnProperty(
     prefix = "spring.aop",
     name = {"proxy-target-class"},
     havingValue = "true",
     matchIfMissing = true
 )
 static class ClassProxyingConfiguration {
     ClassProxyingConfiguration(BeanFactory beanFactory) {
         if (beanFactory instanceof BeanDefinitionRegistry) {
             BeanDefinitionRegistry registry = (BeanDefinitionRegistry)beanFactory;
             AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
             AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
         }

     }
 }

 @Configuration(
     proxyBeanMethods = false
 )
 @ConditionalOnClass({Advice.class})
 static class AspectJAutoProxyingConfiguration {
     AspectJAutoProxyingConfiguration() {
     }

	 // Cglib代理配置
     @Configuration(
         proxyBeanMethods = false
     )
     @EnableAspectJAutoProxy(
         proxyTargetClass = true
     )
     @ConditionalOnProperty(
         prefix = "spring.aop",
         name = {"proxy-target-class"},
         havingValue = "true",
         matchIfMissing = true
     )
     static class CglibAutoProxyConfiguration {
         CglibAutoProxyConfiguration() {
         }
     }

	// Jdk动态代理的配置
     @Configuration(
         proxyBeanMethods = false
     )
     @EnableAspectJAutoProxy(
         proxyTargetClass = false
     )
     @ConditionalOnProperty(
         prefix = "spring.aop",
         name = {"proxy-target-class"},
         havingValue = "false",
         matchIfMissing = false
     )
     static class JdkDynamicAutoProxyConfiguration {
         JdkDynamicAutoProxyConfiguration() {
         }
     }
 }

上述的代码中有个@EnableAspectJAutoProxy关键注解

@Import({AspectJAutoProxyRegistrar.class})
public @interface EnableAspectJAutoProxy {
    boolean proxyTargetClass() default false;
    boolean exposeProxy() default false;
}

发现一个@Import注解,目的是加载AspectJAutoProxyRegistar对应的注解方式的BeanDefinitionReaderConfigurationClassBeanDefinitionReader

// 注册AnnotationAwareAspectJAutoProxyCreator到容器
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
	registrars.forEach((registrar, metadata) ->
			registrar.registerBeanDefinitions(metadata, this.registry));
}

以上代码AnnotationAwareAspectJAutoProxyCreator是以注解的方式注册到容器中

可以发现俩种方式都是对AnnotationAwareAspectJAutoProxyCreator的注册,下面就探究一下这个类:
在这里插入图片描述
标红框的是整个Aop流程的入口点,下面是这个入口点的代码:

// 该函数是SmartInstantiationAwareBeanPostProcessor定义的方法
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
	Object cacheKey = getCacheKey(bean.getClass(), beanName);
	this.earlyProxyReferences.put(cacheKey, bean);
	return wrapIfNecessary(bean, beanName, cacheKey);
}
// 该函数是InstantiationAwareBeanPostProcessor接口定义的方法
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;
		}
	}

	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;
}
// 该函数是BeanPostProcessor定义的方法
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
	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) {
	// targetSourcedBeans里是否存在beanName
	if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
		return bean;
	}
	// 不是继承Advice,Advisor,Pointcut或@Aspect注解标识的直接返回
	if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
		return bean;
	}
	// 判断是否是Aop相关的类(继承Advice,Advisor,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);
		// 创建代理:默认Cglib代理(proxyTargetClass=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;
}

// 看下Jdk动态代理的代码
// class JdkDynamicAopProxy implements AopProxy, InvocationHandler
@Override
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 {
		// ...省略对equals,hashcode函数的增强
		 if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
				method.getDeclaringClass().isAssignableFrom(Advised.class)) {
			// 目标类默认实现Advised接口
			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);

		// Get the interception chain for this method.
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

		if (chain.isEmpty()) {
			Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
			retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
		}
		else {
			// 核心:包含方法的拦截器(该mehod对应的切点【before, after, around等】)
			MethodInvocation invocation =
					new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, 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())) {
			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);
		}
	}
}

总结:在第二章节讲解的bean的创建过程可知,该函数是在每一个bean属性填充前会调用postProcessBeforeInstantiation填充后会调用postProcessAfterInitialization函数(相当于过滤器),postProcessBeforeInstantiation函数目的是记录非切面类的信息,最终的代理工作是在postProcessAfterInitialization中完成的,主要工作有根据目标类路径和切点表达式获取符合条件的通知advisor,然后对目标类方法和通知advisor
的表达式进行判断,判断是否包含此目标方法,如果包含的话再进一步判断此通知的类型(before,after,around,return等)并调用此通知也就对目标方法实现了增强,否则直接利用反射调用此目标方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值