spring源码版本:spring5.0
JDK版本: 1.8
我保存的源码地址:https://gitee.com/paincupid/spring-framework.git
或者官网地址:https://github.com/spring-projects/spring-framework.git
更多源码文章:https://github.com/arthur-dy-lee/arthur-dy-lee-note
AOP是怎么作用到代码上的呢?我觉得从2方面考虑:
1、IOC启动的时候,注册一些AOP相关的类或代码
2、在代码运行时,根据注册的AOP去动态的代理目标对象。
下面先从IOC启动说起。
NamespaceHandlerSupport的继承类AopNamespaceHandler.init方法,为config, spring-configured, aspectj-autoproxy, scoped-proxy 标签注册BeanDefinitionParsers
NamespaceHandlerSupport.parse(AopNamespaceHandler.parse) -> BeanDefinitionParser.parser(AspectJAutoProxyBeanDefinitionParser.parser) -> ParserContext -> XmlReaderContext.getRegistry()-> BeanDefinitionRegistry.registerBeanDefinition(DefaultListableBeanFactory.registerBeanDefinition)
AbstractApplicationContext#refresh()
AbstractRefreshableApplicationContext#refreshBeanFactory
AbstractXmlApplicationContext#loadBeanDefinitions
AbstractBeanDefinitionReader#loadBeanDefinitions
XmlBeanDefinitionReader#loadBeanDefinitions
DefaultBeanDefinitionDocumentReader#registerBeanDefinitions
BeanDefinitionParserDelegate#parseCustomElement
NamespaceHandlerSupport#parse
AspectJAutoProxyBeanDefinitionParser#parse
AopNamespaceUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary
DefaultListableBeanFactory#registerBeanDefinition
最后会贴一张IOC代码的调用顺序图,如果不清楚的话,可以下载xmind文件看高清的。
NamespaceHandlerSupport实现类,图如下所示。
继承结构,图中只写了4个子类
在spring中,如果想要自定义标签:
- 可以继承NamespaceHandlerSupport
- 继承AbstractSingleBeanDefinitionParser,或者实现BeanDefinitionParser接口,在init中注册自定义的BeanDefinitionParser解析器。
- …
NamespaceHandlerSupport有一个很重要的方法:parse,具体的handler会调用这个方法,返回一个BeanDefinition。
NamespaceHandlerSupport属性parsers包括BeanDefinitionParser,BeanDefinitionParser.parser真正解析返回一下BeanDefinition
调用顺序:handler.parse -> BeanDefinitionParser.parser -> return BeanDefinition
private final Map<String, BeanDefinitionParser> parsers = new HashMap<>();
public BeanDefinition parse(Element element, ParserContext parserContext) {
BeanDefinitionParser parser = findParserForElement(element, parserContext);
return (parser != null ? parser.parse(element, parserContext) : null);
}
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
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;
}
初始化定义的标签解析处理器, 为config, spring-configured, aspectj-autoproxy, scoped-proxy 标签注册BeanDefinitionParsers。aop:config包括pointcut, advisor和aspect标签页
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());
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());
}
}
配置如
http\://www.springframework.org/schema/aop/spring-aop-2.0.xsd=org/springframework/aop/config/spring-aop.xsd
http\://www.springframework.org/schema/aop/spring-aop-2.5.xsd=org/springframework/aop/config/spring-aop.xsd
http\://www.springframework.org/schema/aop/spring-aop-3.0.xsd=org/springframework/aop/config/spring-aop.xsd
http\://www.springframework.org/schema/aop/spring-aop-3.1.xsd=org/springframework/aop/config/spring-aop.xsd
http\://www.springframework.org/schema/aop/spring-aop-3.2.xsd=org/springframework/aop/config/spring-aop.xsd
http\://www.springframework.org/schema/aop/spring-aop-4.0.xsd=org/springframework/aop/config/spring-aop.xsd
http\://www.springframework.org/schema/aop/spring-aop-4.1.xsd=org/springframework/aop/config/spring-aop.xsd
http\://www.springframework.org/schema/aop/spring-aop-4.2.xsd=org/springframework/aop/config/spring-aop.xsd
http\://www.springframework.org/schema/aop/spring-aop-4.3.xsd=org/springframework/aop/config/spring-aop.xsd
http\://www.springframework.org/schema/aop/spring-aop.xsd=org/springframework/aop/config/spring-aop.xsd
内置的xsd文件,文件内容包含了命名空间处理器AopNamespaceHandler对于标签处理的规则
BeanDefinition被DefaultBeanDefinitionDocumentReader使用,用来解析标签页,将BeanDefinition注册给BeanDefinitionRegistry,并返回BeanDefinition
所有解析器,都是由 BeanDefinitionParser 接口的统一实现,入口都是从 parse函数开始的 。
public interface BeanDefinitionParser {
@Nullable
BeanDefinition parse(Element element, ParserContext parserContext);
}
如下图所示:
AnnotationDrivenBeanDefinitionParser、AspectJAutoProxyBeanDefinitionParser、ConfigBeanDefinitionParser、SpringConfiguredBeanDefinitionParser这些类,并不返回BeanDefinition,在方法parse(Element element, ParserContext parserContext)主要是对BeanDefinition进行注册,保存起来。
public BeanDefinition parse(Element element, ParserContext parserContext) {
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
extendBeanDefinition(element, parserContext);
return null;
}
public final class ParserContext {
private final XmlReaderContext readerContext;
private final BeanDefinitionParserDelegate delegate;
@Nullable
private BeanDefinition containingBeanDefinition;
public final BeanDefinitionRegistry getRegistry() {
return this.readerContext.getRegistry();
}
}
下面会介绍DefaultListableBeanFactory会继承BeanDefinitionRegistry,然后进行注册BeanDefinition到一个concurrentHashMap中。
一定要讲一下 TxAdviceBeanDefinitionParser 这个类,主要是为了 tx:advice 标签页的使用,这个单独拉一章讲。
4.2只讲了AspectJAutoProxyBeanDefinitionParser,在AopNamespaceHandler初始化的时候,还有其它AOP标签,如:
DefaultListableBeanFactory有一个很重要的作用就是注册和保存BeanDefinition。
可以看到DefaultListableBeanFactory实现了BeanDefinitionRegistry接口,通过方法registerBeanDefinition,将BeanDefinition注册到DefaultListableBeanFactory中去。这也是IOC初始化的一部分。
private final Map
beanDefinitionMap = new ConcurrentHashMap<>(256); public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
从代码可以看到,属性beanDefinitionMap 中存放的BeanDefinition。
以及通过方法registerBeanDefinition,将BeanDefinition注册到DefaultListableBeanFactory中去。
更新源码文章:https://github.com/arthur-dy-lee/arthur-dy-lee-note