1. 标签的解析
因为在spring 的配置中,默认解析的标签只有 bean beans import alias 这四种,所以了解aop实现的第一步,就需要先从 aop标签的解析
关于bean 的解析,在 DefaultBeanDefinitionDocumentReader.java 中
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element ele) {
if (delegate.isDefaultNamespace(ele)) {
// 默认的 bean、beans、alias、import 的解析
parseDefaultElement(ele, delegate);
}
else {
// 通过 一个BeanDefinition的Parser 代理解析第三方的标签
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
// import 标签
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
// alias 标签
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
// bean 标签
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
// beans 标签
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
1.1 找到 namespaceUri
当我们点进去 BeanDefinitionParserDelegate.java 中的 delegate.parseCustomElement(root) 这一句的实现时
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
// 先找到标签对应的 namespaceUri 命名空间
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
// 根据 命名空间找到对应的 NamespaceHandler
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
// 根据自定义的 NamespaceHanlder 进行解析
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
在 getNamespaceURI(ele) 中,是通过获取 node.getNamespaceURI(); aop 的就是 http://www.springframework.org/schema/aop。
1.2 通过 namespaceUri 找到对应的 NamespaceHandler。
看 DefaultNamespaceHandlerResolver.java 中的 resolve 方法
public NamespaceHandler resolve(String namespaceUri) {
// 获取所有已经配置的 handler 映射
Map<String, Object> handlerMappings = this.getHandlerMappings();
// 根据命名空间找到对应的信息,这里是 handler Or className 两种状态
Object handlerOrClassName = handlerMappings.get(namespaceUri);
if (handlerOrClassName == null) {
return null;
} else if (handlerOrClassName instanceof NamespaceHandler) {
// 如果已经解析完成,从缓存中获取
return (NamespaceHandler)handlerOrClassName;
} else {
// 如果没有解析,返回的是类路径
String className = (String)handlerOrClassName;
try {
// className 转化成 class
Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri + "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
} else {
// 初始化类
NamespaceHandler namespaceHandler = (NamespaceHandler)BeanUtils.instantiateClass(handlerClass);
// 调用 init() 方法
namespaceHandler.init();
// 放到缓存map里面
handlerMappings.put(namespaceUri, namespaceHandler);
return namespaceHandler;
}
} catch (ClassNotFoundException var7) {
throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "] not found", var7);
} catch (LinkageError var8) {
throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]: problem with handler class file or dependent class", var8);
}
}
}
通过debug,可以看到 handlerMappings 里面的内容
可以看到 aop 的解析具体实现是通过org.springframework.aop.config.AopNamespaceHandler 实现的。
1.3 执行handler.parse
在获取到 NamespaceHandler 之后,spring就将解析工作委托给 自定义解析去取解析了
来到 NamespaceHandlerSupport.java 是一个 abstract 抽象类。
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 寻找到解析器
BeanDefinitionParser parser = findParserForElement(element, parserContext);
// 执行解析操作
return (parser != null ? parser.parse(element, parserContext) : null);
}
1.3.1 寻找解析器
@Nullable
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
// 获取元素名称,例如 aspectj-autoproxy 之类的
String localName = parserContext.getDelegate().getLocalName(element);
// 找到对应的 解析器
BeanDefinitionParser parser = this.parsers.get(localName);
if (parser == null) {
parserContext.getReaderContext().fatal(
"Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
}
return parser;
}
1.3.2 执行解析
parser.parse(element, parserContext)
2. AopNamespaceHandler
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.5+ XSDs
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
// Only in 2.0 XSD: moved to context namespace in 2.5+
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}
通过上一步我们知道,当遇到 aspectj-autoproxy 标签的时候,会调用 AspectJAutoProxyBeanDefinitionParser 进行解析,接下来的全部以 aspectj-autoproxy 为例。
2.1 关于 AspectJAutoProxyBeanDefinitionParser
class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 注册 AnnotationAwareAspectJAutoProxyCreator
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
// 对于注解中的子类处理
extendBeanDefinition(element, parserContext);
return null;
}
}
其中的AopNamespaceUtils 中的静态方法registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element) 是我们比较关心的。
// 注册 AnnotationAutoProxyCreator
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
// 注册或升级 beanName是 org.springframework.aop.config.internalAutoProxyCreator 的BeanDefinition
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
// 处理 proxy-target-class 和 expose-proxy 属性
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
// 注册组件并且通知,以便监听器做进一步处理
registerComponentIfNecessary(beanDefinition, parserContext);
}
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
if (sourceElement != null) {
// proxy-target-class tags
boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
// expose-proxy tags
boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
private static void registerComponentIfNecessary(@Nullable BeanDefinition beanDefinition, ParserContext parserContext) {
if (beanDefinition != null) {
// 注册组件
parserContext.registerComponent(
new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME));
}
}
其中的重点是 registerAspectJAnnotationAutoProxyCreatorIfNecessary
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
@Nullable
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);
// 注册到 beanFactory
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
2.2 关于 AnnotationAwareAspectJAutoProxyCreator
他可以根据 @Ponit 注解定义的切点来自动代理相匹配的bean。
可以看到 他还实现了 BeanPostPorcessor 接口,在实现 BeanPostPorcessor 接口之后,当Spring 加载这个Bean的时候会在实例化前调用postProcessAfterInitialization